Reputation: 121
I want to change the scoring function of my Search Engine in Lucene 5.2.1. I just want to add the output of a function f to the default lucene's score. Something like this:
myScore = defaultScore + f(field1, field2)
Where f is a simple calculus on two indexed document fields (containing a numeric value). This link proves that it should be possible to do this kind of things, but no snippet is provided at all.
Finally, you can extend the low level Similarity directly to implement a new retrieval model, or to use external scoring factors particular to your application. For example, a custom Similarity can access per-document values via NumericDocValues and integrate them into the score.
Anybody knows how to do it? Many thanks
Upvotes: 0
Views: 759
Reputation: 1237
I think CustomScoreQuery may be what you want. The link of CustomScoreQuery is
in Lucene 5.2.1. Following is code snippet about trying to get your problem done with Lucene 3.6.2 in Scala
.
import org.apache.lucene.index.{ Term, IndexReader }
import org.apache.lucene.search.{ TermQuery, Query }
import org.apache.lucene.search.function.{ CustomScoreProvider, CustomScoreQuery }
class CustomizedScoreProvider(reader: IndexReader) extends
CustomScoreProvider(reader) {
protected override def customScore(doc: Int,
subQueryScore: Float, valSrcScores: Array[Float]): Float = {
try {
// subQueryScore is the default score you get from
// the original Query
val currentDocument = reader.document(doc)
// get the value of two field1, field2,
// make sure the two fields are stored since you have to retrieve the value
val field1Value = currentDocument.get("field1")
val field2Value = currentDocument.get("field2")
// write your own logical to compute the extra score, assuming 0 here
val extraScore = 0F
// ignore the valSrcScores here, the original calculation
// is modifiedScore = subQueryScore*valSrcScores[0]*..
subQueryScore + extraScore
} catch {
case _: Exception => subQueryScore
}
}
}
/**
* Create a CustomScoreQuery over input subQuery.
* @param subQuery the sub query whose scored is being customized. Must not be null.
*/
class CustomizedScoreQuery(val subQuery: Query, reader: IndexReader)
extends CustomScoreQuery(subQuery) {
protected override def getCustomScoreProvider(reader: IndexReader) = {
try {
new CustomizedScoreProvider(reader)
} catch {
case _: Exception => super.getCustomScoreProvider(reader)
}
}
}
object CustomizedScoreQueryTest extends App {
val termQuery = new TermQuery(new Term("field", "xxx"))
// get indexSearch, indexReader and wrap the original query
...
val wrappedQuery = new CustomizedScoreQuery(termQuery, indexReader)
val topDocs = indexSearch.search(wrappedQuery, 5)
...
}
Actually, I got stuck with the same problem when I saw your question and finally got it done with CustomScoreQuery. When you use CustomScoreQuery to change the default score, say when sorting by relevance, the document order will change according to the modified score.
Anyway, hope it helps.
Upvotes: 1