lucene 的评分机制

来源:互联网 发布:尘埃3 for mac 编辑:程序博客网 时间:2024/04/27 14:25
该部分转自:http://grantbb.iteye.com/blog/181802 
    通过Searcher.explain(Query query, int doc)方法可以查看某个文档的得分的具体构成。在Lucene中score简单说是由:tf*idf*t*lengthNorm计算得出的。 
     tf:是查询的词在文档中出现的次数的平方根; idf:表示反转文档频率; boost:激励因子,可以通过setBoost方法设置,需要说明的通过field和doc都可以设置,所设置的值会同时起作用; lengthNorm:是由搜索的field的长度决定了,越长文档的分值越低。 
    所以,我们编程能够控制的scroe,就是设置boost的值。 
    为什么一次查询后,最大的分值总是1呢?因为lucene会把计算后,最大分值超过1.0的分值作为分母,其他文档的分值都除以这个最大值,计算出最终得分。 
01public class ScoreSortTest {
02    public final static String INDEX_STORE_PATH = "index";
03    public static void main(String[] args) throws Exception {
04        IndexWriter writer = new IndexWriter(INDEX_STORE_PATH, new StandardAnalyzer(), true);
05        writer.setUseCompoundFile(false);
06         
07        Document doc1 = new Document();
08        Document doc2 = new Document();
09        Document doc3 = new Document();
10         
11        Field f1 = new Field("bookname","bc bc", Field.Store.YES, Field.Index.TOKENIZED);
12        Field f2 = new Field("bookname","ab bc", Field.Store.YES, Field.Index.TOKENIZED);
13        Field f3 = new Field("bookname","ab bc cd", Field.Store.YES, Field.Index.TOKENIZED);
14         
15        doc1.add(f1);
16        doc2.add(f2);
17        doc3.add(f3);
18         
19        writer.addDocument(doc1);
20        writer.addDocument(doc2);
21        writer.addDocument(doc3);
22         
23        writer.close();
24         
25        IndexSearcher searcher = new IndexSearcher(INDEX_STORE_PATH);
26        TermQuery q = new TermQuery(new Term("bookname""bc"));
27        q.setBoost(2f);
28        Hits hits = searcher.search(q);
29        for(int i=0; i<hits.length();i++){
30            Document doc = hits.doc(i);
31            System.out.print(doc.get("bookname") + "\t\t");
32            System.out.println(hits.score(i));
33            System.out.println(searcher.explain(q, hits.id(i)));//
34        }
35    }
36}
结果为: 
 
    说明,从结果中我们可以看到: 
     bc bc文档中bc出现了2次,tf为2的平方根,所以是1.4142135。而其他的两个文档出现了一次,所以是1.0 
所有的三个文档的idf值都是一样的,是0.71231794。默认情况下,boost的值都是1.0,所以lengthNorm就是当前的fieldNorm的值。前两个文档的长度一致,为0.625,而排在最后的文档,因为长度要长一些,所以分值要低,为0.5 
    现在对f2这个字段增加激励因子:f2.setBoost(2.0f);运行结果变为: 
 
    发现fieldNorm值有0.625变成了1.25,所以就是乘以了2.0。接下来再对第二个文档增加激励因子:doc2.setBoost(2.0f);运行结果变为: 
 
    发现fieldNorm又乘以了2,所以说对于Document和Field的setBoost都会乘到一起。因为该文档的最终的score超过了1.0变成1.7807949,所以其他的两个文档的最终得分都要除以该值,分别变成: 
bc bc 0.35355335 ab bc cd 0.19999999

0 0
原创粉丝点击