ElasticSearch源码解析(五):排序(评分公式)

ElasticSearch源码解析(五):排序(评分公式)

转载自:http://blog.csdn.net/molong1208/article/details/50623948

 

一、目的

一个搜索引擎使用的时候必定需要排序这个模块,一般情况下在不选择按照某一字段排序的情况下,都是按照打分的高低进行一个默认排序的,所以如果正式使用的话,必须对默认排序的打分策略有一个详细的了解才可以,否则被问起来为什么这个在前面,那个在后面不好办,因此对Elasticsearch的打分策略详细的看了下,虽然说还不是了解的很全部,但是大部分都看的差不多了,结合理论以及搜索的结果,做一个简单的介绍

二、Elasticsearch的打分公式

Elasticsearch的默认打分公式是lucene的打分公式,主要分为两部分的计算,一部分是计算query部分的得分,另一部分是计算field部分的得分,下面给出ES官网给出的打分公式:

 
 在CODE上查看代码片派生到我的代码片
  1. score(q,d)  =    
  2.             queryNorm(q)    
  3.           · coord(q,d)      
  4.           · ∑ (             
  5.                 tf(t in d)     
  6.               · idf(t)²        
  7.               · t.getBoost()   
  8.               · norm(t,d)      
  9.             ) (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

所以按照计算公式

 在CODE上查看代码片派生到我的代码片
  1. 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

所以总体的计算就是

  1. score=queryweight*fieldweight=idf*queryNorm(d)*idf*tf*fieldnorm=coord*queryNorm(d)*tf*idf^2*fieldnormview pl
原文地址:https://www.cnblogs.com/bonelee/p/8358210.html