ElasticSearch源碼解析(五):排序(評分公式)
轉載自:http://blog.csdn.net/molong1208/article/details/50623948
一、目的
一個搜索引擎使用的時候必定需要排序這個模塊,一般情況下在不選擇按照某一字段排序的情況下,都是按照打分的高低進行一個默認排序的,所以如果正式使用的話,必須對默認排序的打分策略有一個詳細的了解才可以,否則被問起來為什么這個在前面,那個在后面不好辦,因此對Elasticsearch的打分策略詳細的看了下,雖然說還不是了解的很全部,但是大部分都看的差不多了,結合理論以及搜索的結果,做一個簡單的介紹
二、Elasticsearch的打分公式
Elasticsearch的默認打分公式是lucene的打分公式,主要分為兩部分的計算,一部分是計算query部分的得分,另一部分是計算field部分的得分,下面給出ES官網給出的打分公式:
- score(q,d) =
- queryNorm(q)
- · coord(q,d)
- · ∑ (
- tf(t in d)
- · idf(t)²
- · t.getBoost()
- · norm(t,d)
- ) (t in q)
queryNorm(q):
對查詢進行一個歸一化,不影響排序,因為對於同一個查詢這個值是相同的,但是對term於ES來說,必須在分片是1的時候才不影響排序,否則的話,還是會有一些細小的區別,有幾個分片就會有幾個不同的queryNorm值
queryNorm(q)=1 / √sumOfSquaredWeights
上述公式是ES官網的公式,這是在默認query boost為1,並且在默認term boost為1 的情況下的打分,其中
sumOfSquaredWeights =idf(t1)*idf(t1)+idf(t2)*idf(t2)+...+idf(tn)*idf(tn)
其中n為在query里面切成term的個數,但是上面全部是在默認為1的情況下的計算,實際上的計算公式如下所示:
三、實際的打分explain
在實際的時候,例如搜索“無線通信”,如下圖所示,因為一些私人原因,將一些字段打碼,查詢的時候設置explain為true,如下圖所示:
因為使用的是默認的分詞器,所以最后的結果是將“無線通信”分成了四個字,並且認為是四個term來進行計算,最后將計算的結果進行相加得到最后的得分0.7605926,這個分數是“無”的得分+“線”的得分+“通”的得分+“信”的得分,四個term的得分如下圖所示:
最后的得分是0.7605926=0.118954286+0.1808154+0.14515185+0.31567,與上述符合,因為四個詞都出現了所以在這里面的coord=1,總分數的計算知道后,我們單看每一部分的得分的計算,以“無”為例進行介紹:
其中每一個term內部分為兩部分的分數,一部分是queryweight,一部分是fieldweight,其中總分數=queryweight*fieldweight
例如此處queryweight=0.51195854,fieldWeight=0.2323514,所以總的分數就是0.118954286
queryweigth計算:
對於queryweight部分的計算分為兩個部分idf和querynorm,其中idf的值是2.8618271,這個值是如何計算的呢
idf=1+ln(1995/(309+1))=2.8618271,說明在分片四里面共有1995個文檔,召回了包含“無”的309個文檔,因此為這個值
querynorm部分的計算:根據上面“無”“線”“通”“信”四個的分數計算,可以看到,idf的值分別為
無:2.8618271
線:3.1053379
通:2.235371
信:2.901306
所以按照計算公式
- querynorm=1 / √2.8618271*2.8618271+3.1053379*3.1053379+2.235371*2.235371+2.901306*2.901306=0.1788922
所以queryweight部分的值是0.1788922*2.8618271=0.51195854
再次總結下此處的公式:queryweight=idf*queryNorm(d)
fieldweight部分計算:
idf的計算上邊已經算過,在此不詳細敘述
tf的值是在此處出現3次,所以為√3=1.7320508
fieldnorm的值不知道如何計算,按照公式計算不出來explain的值,網上資料說是編解碼導致的,哪位朋友知道如何計算麻煩回復下,多謝
總結下fieldweight部分的計算公式:fieldweight=idf*tf*fieldnorm=1.7320508*2.8618271*0.046875=0.2323514
所以總體的計算就是
- score=queryweight*fieldweight=idf*queryNorm(d)*idf*tf*fieldnorm=coord*queryNorm(d)*tf*idf^2*fieldnormview pl