引自
http://www.javaeye.com/wiki/Lucene/1526-lucene-39-s-score-score-a-simple-mechanism-to-explain
通过Searcher.explain(Query query, int doc)方法可以查看某个文档的得分的具体构成。
在Lucene中score简单说是由 tf * idf * boost * lengthNorm计算得出的。
tf:是查询的词在文档中出现的次数的平方根
idf:表示反转文档频率,观察了一下所有的文档都一样,所以那就没什么用处,不会起什么决定作用。
boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值会同时起作用
lengthNorm:是由搜索的field的长度决定了,越长文档的分值越低。
所以我们编程能够控制score的就是设置boost值。
还有个问题,为什么一次查询后最大的分值总是1.0呢?
因为Lucene会把计算后,最大分值超过1.0的分值作为分母,其他的文档的分值都除以这个最大值,计算出最终的得分。
下面用代码和运行结果来进行说明:
public class ScoreSortTest { public final static String INDEX_STORE_PATH = "index"; public static void main(String[] args) throws Exception { IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true); writer.setUseCompoundFile(false); Document doc1 = new Document(); Document doc2 = new Document(); Document doc3 = new Document(); Field f1 = new Field("bookname","bc bc", Field.Store.YES, Field.Index.TOKENIZED); Field f2 = new Field("bookname","ab bc", Field.Store.YES, Field.Index.TOKENIZED); Field f3 = new Field("bookname","ab bc cd", Field.Store.YES, Field.Index.TOKENIZED); doc1.add(f1); doc2.add(f2); doc3.add(f3); writer.addDocument(doc1); writer.addDocument(doc2); writer.addDocument(doc3); writer.close(); IndexSearcher searcher = new IndexSearcher(INDEX_STORE_PATH); TermQuery q = new TermQuery(new Term("bookname", "bc")); q.setBoost(2f); Hits hits = searcher.search(q); for(int i=0; i<hits.length();i++){ Document doc = hits.doc(i); System.out.print(doc.get("bookname") + "/t/t"); System.out.println(hits.score(i)); System.out.println(searcher.explain(q, hits.id(i)));// } } }
运行结果: