Lucene Scoring 评分公式:
score(q,d) = coord(q,d) · queryNorm(q) · ∑ ( tf(t in d) · idf(t)2 · t.getBoost() · norm(t,d) )
1. 公式详解:
coord(q , d):
一次搜索可能包含多个搜索词,而一篇文档中也可能包含多个搜索词,此项表示,当一篇文档中包含的搜索词越多,则此文档则打分越高。
评分因子,是基于文档中出现查询项的个数。越多的查询项在一个文档中,说明些文档的匹配程序越高。默认是出现查询项的百分比。
queryNorm(q):
计算每个查询条目的方差和,此值并不影响排序,而仅仅使得不同的query之间的分数可以比较。其公式如下:
tf(t in d):
Term t在文档d中出现的词频
idf(t):
Term t在几篇文档中出现过
norm(t, d):
标准化因子,它包括三个参数:
Document boost:
此值越大,说明此文档越重要。
Field boost:
此域越大,说明此域越重要。
lengthNorm(field) = (1.0 / Math.sqrt(numTerms)):
一个域中包含的Term总数越多,也即文档越长,此值越小,文档越短,此值越大。
在做索引的时候由 Similarity.lengthNorm 计算。
2. 公式原理推导:
首先,将以上各部分代入score(q, d)公式,将得到一个非常复杂的公式,让我们忽略所有的boost,因为这些属于人为的调整,也省略coord,这和公式所要表达的原理无关。得到下面的公式:
索引的时候,把 norm 值压缩(encode)成一个 byte 保存在索引中。搜索的时候再把索引中 norm 值解压(decode)成一个 float 值,这个 encode/decode 由 Similarity 提供。官方说:这个过程由于精度问题,以至不是可逆的,如:decode(encode(0.89)) = 0.75。
计算这个评分涉及到几个核心的类/接口:Similarity、Query、Weight、Scorer、Searcher,由它们或其子类来完成评分的计算。