zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    第36课 经典问题解析三
    第35课 函数对象分析
    67. Add Binary
    66. Plus One
    58. Length of Last Word
    53. Maximum Subarray
    38. Count and Say
    35. Search Insert Position
    28. Implement strStr()
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/bonelee/p/8358210.html
Copyright © 2011-2022 走看看