3.3 理解Lucene的评分机制
为了使读者能够对影响Lucene评分的各个因素有一个全面的认识,我们在这章就来讨论一下这个复杂的主题。首先,我们来看一下图3.1中的相似度评分公式。Lucene会为由某一指定查询匹配到的每个文档d使用这个公式计算其相应的得分。
图3.1 Lucene利用这个公式计算出匹配于某一查询的文档的评分
注:如果你对这个方程式或者这种数学计算思想的理解存在一定困难,可以跳过这个小节。Lucene的评分机制是相当拔尖非常优秀的,但完全理解Lucene的评分机制如何工作并不需要使用Lucene的各项功能。
通过这个评 分公式得到的只是原始的得分,但由Hits对象返回的关于某一文档的评分却不一定是其原始的得分。因为,评分最高的文档的得分如果超过了1.0,那么接下 来的所有评分都会以这个评分为标准进行计算,因此所有Hits对象的得分都只能小于或等于1.0。表3.5列出了在评分公式中的各个因子。
表3.5 评分公式中的因子
评分因子 | 描 述 |
tf(t in d) | 文档d中出现搜索项t的频率 |
idf(t) | 搜索项t在倒排文档中出现的频率 |
boost(t.field in d) | 域的加权因子(boost),它的值在索引过程中进行设置 |
lengthNorm(t.field in d) | 域的标准化值(normalization value),即在某一域中所有项的个数。通常在索引时计算该值并将其存储到索引中 |
coord(q, d) | 协调因子(Coordination factor),该因子的值基于文档中包含查询的项的个数 |
queryNorm(q) | 每个查询的标准化值,指每个查询项权重的平方和 |
在 公式中加入加权因子(boost factor),可使你有效地对某个查询或某一域给评分带来的影响施加控制。Lucene在索引时,显式地通过boost(t.field in d)来设置某个域的加权因子。该加权因子的默认值为1.0。在索引期间,也可以为Document对象设置加权因子。它隐式地把该文档中所有域的初始加权 因子都设置为指定值。特定域的加权因子是初始加权因子的倍数,经过一定处理后才最终得出该域加权因子的值。在索引过程中,有可能多次将同一域添加到同一个 文档中,在这种情况下,该域的加权因子就等于该域在这个文档的所有加权因子之和。在2.3小节中我们就曾经讨论过在索引时对某个域进行加权处理的问题。
在这个公式 中除了一些明确的因子外,其他一部分作为查询标准(queryNorm)的因子可以在每次查询的基础上计算出来。Query对象本身对匹配文档的评分也会 产生一定的影响。加权处理某一Query对象仅在应用程序执行多重子句的查询时比较有效;如果只搜索单个项,加权处理该项相当于同时对所有匹配该项的文档 都进行了相同比例的加权。在多重子句的布尔查询中,一些文档可能只匹配其中的一个子句,使用不同的加权因子可以用来区分不同的查询条件。Query对象加 权因子的值也默认为1.0。
在这个评分 公式中,对绝大多数因子的控制都是通过Similarity实例来实现的。如果不另外指定,在默认的情况下Lucene会用 DefaultSimilarity来实现Similarity类。此外,DefaultSimilarity类还负责处理评分中更多的计算过程,例如, 项频率(term frequency)因子就是实际频率的平方根。因为这是一本讲述如何“实践”的书籍所提到的,故深入研究这些核心运算过程已经超出了本书的范围。实际 上,这些因子是极少需要改变的。如果你需要改变这些因子,请参考Similarity类的相关文档,但同时必须对这些因子的作用有很好的理解,并清楚改变 它们后有可能带来的结果。此外还要注意,索引过程中改变加权因子或使用了Similarity类的方法后,为了同时协调所有的相关因子,应用程序需要对索 引进行重建。