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
  • 相关阅读:
    webpack配置之代码优化
    react组件生命周期
    javascript记住用户名和登录密码
    ajax异步请求原理和过程
    深入理解ajax系列第五篇——进度事件
    ajax多次请求,只执行最后一次的方法
    CentOS6.8下MySQL MHA架构搭建笔记
    HTTP状态码
    什么是 Redis 事务?原理是什么?
    Redis 通讯协议是什么?有什么特点?
  • 原文地址:https://www.cnblogs.com/bonelee/p/8358210.html
Copyright © 2011-2022 走看看