理解Apache Lucene的评分算法

Tej*_*jas 2 lucene search solr full-text-search hibernate-search

我已经使用 Hibernate Search 几个月了,但我仍然无法消化它带来的相关性。我对它返回的结果总体满意,但即使是最简单的测试也不能满足我的期望。

第一个测试是使用术语频率(tf)。数据:

  • 单词
  • 字字
  • 词词词
  • 词词词词
  • 词词词词词
  • 词词词词词词词

我得到的结果:

  1. 单词
  2. 词词词词
  3. 词词词词词
  4. 词词词词词词词
  5. 字字
  6. 词词词

我真的对这种得分效应感到困惑。我的查询很复杂,但是由于这个测试没有涉及任何其他字段,它可以简化如下:booleanjunction.should(phraseQuery).should(keywordQuery).should(fuzzyQuery)

我有如下分析器:

 StandardFilterFactory
 LowerCaseFilterFactory
 StopFilterFactory
 SnowballPorterFilterFactory for english
Run Code Online (Sandbox Code Playgroud)

我的解释对象 https://jsfiddle.net/o51kh3og/

ale*_*exf 5

评分计算是一件非常复杂的事情。在这里,你必须从原始方程开始:

score(q,d) = coord(q,d) · queryNorm(q) · ? ( tf(t in d) · idf(t)2 · t.getBoost() · norm(t,d) )

正如你所说,你有tf这意味着词频,它的值是词频的平方根。

但是在这里,正如您在解释中看到的,您还有norm(又名fieldNorm)用于fieldWeight计算。让我们以你的例子为例:

埃克拉维亚 埃克拉维亚 埃克拉维亚 埃克拉维亚 埃克拉维亚

4.296241 = fieldWeight in 177, product of:
  2.236068 = tf(freq=5.0), with freq of:
    5.0 = termFreq=5.0
  4.391628 = idf(docFreq=6, maxDocs=208)
  0.4375 = fieldNorm(doc=177)
Run Code Online (Sandbox Code Playgroud)

埃克拉维亚

4.391628 = fieldWeight in 170, product of:
  1.0 = tf(freq=1.0), with freq of:
    1.0 = termFreq=1.0
  4.391628 = idf(docFreq=6, maxDocs=208)
  1.0 = fieldNorm(doc=170)
Run Code Online (Sandbox Code Playgroud)

在这里,eklavya比另一个有更好的分数,因为fieldWeighttfidf和的乘积fieldNormeklavya文档的最后一个更高,因为他只包含一个术语。

正如上面的文档所说:

lengthNorm - 根据文档中该字段的标记数量将文档添加到索引时计算,以便较短的字段对分数的贡献更大。

你在一个领域里的术语越多,就越低fieldNorm请注意此字段

所以,总而言之,在这里你有一个完美的组合来理解分数不仅用频率计算,而且还用你在你的领域中的术语数计算。