Lucene的评分机制

来源:互联网 发布:软件项目考核管理办法 编辑:程序博客网 时间:2024/06/09 23:56
征服Ajax+Lucene—构建搜索引擎
 

11.3.2  Lucene评分算法

那么,Lucene中是如何确定各个Document评分的呢?下面将详细介绍该功能的基本原理。

文档的得分是在用户进行检索时实时计算出来的。如果在建立索引时就已经将每个文档的得分计算好,那么当用户输入任何关键字时,得分最高的文档都会被排在返回结果的最前面,这显然是不合理的。

因此,所有文档的得分应当都与用户输入的关键字有关系,而且是实时运算的结果。其实,所谓得分,可以简单理解成是某个关键字在某文档中出现的频率。

11-6所示的公式就是Lucene用于计算某个关键字在对应于某文档的得分。

11-6  Lucene的得分公式

Lucene得分公式中,已经包含了影响文档评分的各种因素。在表11.1中详细介绍了每一种因素对搜索结果评分的影响作用。

11-1                                                 Lucene得分公式的解释

   

在公式中的作用描述

tf(t in d)

词条t在文档d中出现的词频

idf( t )

词条t在文档中的倒排词频

boost(t.field in d)

在索引过程中设置的字段参数

lengthNorm(t.field in d)

字段的标准化值,表明在字段中存储了多少词条,这个数值是在索引过程中计算出来的,并且也存储在索引中

coord(q, d)

协调因子,它的计算是基于文档d中所包含的所有可供查询的词条数量

queryNorm(q)

在给出每个查询条目的方差和后,计算某查询的标准化值

 

11.3.3  改变文档的得分

除了内置的得分算法外,Lucene还提供了一种方法来改变每个文档的得分。

在代码11.3中,初始化Document后,使用了DocumentsetBoost方法来改变一下文档的boost因子。这种做法的实际目的是将文档的得分乘以这个因子,以这个新的数作为文档的得分。

代码11.3  使用Boost的例子

public static void buildIndex() throws Exception {

     //生成新的Document对象,下同

    Document doc1 = new Document();

    doc1.add(Field.Text("contents", "word1 word"));

    doc1.add(Field.Keyword("path", "path//document1.txt"));

     //改变文档的boost因子,下同

    doc1.setBoost(1.0f);

   

    Document doc2 = new Document();

    doc2.add(Field.Text("contents", "word2 word"));

    doc2.add(Field.Keyword("path", "path//document2.txt"));

    doc2.setBoost(0.1f);

   

    Document doc3 = new Document();

    doc3.add(Field.Text("contents", "word3 word"));

    doc3.add(Field.Keyword("path", "path//document3.txt"));

    doc3.setBoost(0.5f);

   

    Document doc4 = new Document();

    doc4.add(Field.Text("contents", "word4 word"));

    doc4.add(Field.Keyword("path", "path//document4.txt"));

    doc4.setBoost(0.2f);

   

    Document doc5 = new Document();

    doc5.add(Field.Text("contents", "word5 word"));

    doc5.add(Field.Keyword("path", "path//document5.txt"));

    doc5.setBoost(0.8f);

   

    Document doc6 = new Document();

    doc6.add(Field.Text("contents", "word6 word"));

    doc6.add(Field.Keyword("path", "path//document6.txt"));

    doc6.setBoost(0.1f);

   

    Document doc7 = new Document();

    doc7.add(Field.Text("contents", "word7 word"));

    doc7.add(Field.Keyword("path", "path//document7.txt"));

    doc7.setBoost(0.5f);

   

    Document doc8 = new Document();

    doc8.add(Field.Text("contents", "word8 word"));

    doc8.add(Field.Keyword("path", "path//document8.txt"));

    doc8.setBoost(0.7f);

   

    Document doc9 = new Document();

    doc9.add(Field.Text("contents", "word9 word"));

    doc9.add(Field.Keyword("path", "path//document9.txt"));

    doc9.setBoost(0.2f);

   

    Document doc10 = new Document();

    doc10.add(Field.Text("contents", "word10 word"));

    doc10.add(Field.Keyword("path", "path//document10.txt"));

    doc10.setBoost(0.4f);

   

    Document doc11 = new Document();

    doc11.add(Field.Text("contents", "word11 word"));

    doc11.add(Field.Keyword("path", "path//document11.txt"));

   

    Document doc12 = new Document();

    doc12.add(Field.Text("contents", "word12 word"));

    doc12.add(Field.Keyword("path", "path//document12.txt"));

   

    IndexWriter writer = new IndexWriter("c://index", new StandardAnalyzer(), true);

    //添加到索引中,下同

    writer.addDocument(doc1);

    writer.addDocument(doc2);

    writer.addDocument(doc3);

    writer.addDocument(doc4);

    writer.addDocument(doc5);

    writer.addDocument(doc6);

    writer.addDocument(doc7);

    writer.addDocument(doc8);

    writer.addDocument(doc9);

    writer.addDocument(doc10);

    writer.addDocument(doc11);

    writer.addDocument(doc12);

   

    writer.close();

  }

代码11.3的运行效果,如图11-7所示。

 

11-7  改变Boost后的运行效果

从图11-7可以看出,每个文档的分值已经发生了变化,其中,由于文档11112boost值和原来一样,因此分值排在最前面,显示的顺序也到了最前面。而其他的文档则已经因为boost值发生了改变,显示的顺序也发生了变化。可以看到,排在最后一个位置的文档是文档6,它的boost值为0.1,所以分值也成了原来的十分之一。

像代码11.3中这样通过Boost值来改变分值的方式相当灵活,可以很有效的达到对文档顺序进行控制的目的。不过,这仍然不是一种理想的方式,因为在建立索引时还需要人为地指定每个文档的boost值。

原创粉丝点击