solr的debugQuery打分结果分析

官方文档传送门:http://lucene.apache.org/core/5_2_1/core/org/apache/lucene/search/similarities/TFIDFSimilarity.html

参考源码:org.apache.lucene.search.similarities.DefaultSimilarity


搜索内容

//搜索词: 运动休闲。拆词的结果是[运动、休闲]  
q=运动休闲
//加权类型              
defType=edismax
//具体字段加权数值,搜索字段就是下面设置了权重的字段      
//商品名称加权设置为300  商品关键字加权设置为100 
qf=productName^300 labels^100
//有库存的加权设置为1500
bf=sum(abs(hasStock))^1500


商品名:AITAO艾涛女士休闲运动反光夹克

拆词:aitao 艾涛 女士 休闲 运动 反光 夹克

关键字:夹克 上衣 女装 长袖 运动装 毛衫


打分结果

//总得分,取下面几项的和
// 2.6362033 = 2.0421042 + 0.5940989
2.6362033 = sum of:
  // 文档得分,取字段得分最大的那个
  2.0421042 = max of: 
    // 商品名称字段各查询词的得分和
    // 2.0421042 = 1.2281255 + 0.8139789
    2.0421042 = sum of: 
      // 具体查询词的得分数
      1.2281255 = weight(productName:运动 in 16295) [DefaultSimilarity], result of: 
        // doc=16295表示文档的编号是16295,这个编号是自动生成的
        // product of:  结尾则表示取下面子项的乘机值 1.2281255 = 0.62380683 * 1.9687593
        1.2281255 = score(doc=16295,freq=1.0), product of: 
          // 0.62380683 = 5.250025 * 0.11881979
          0.62380683 = queryWeight, product of: 
            // 逆向文档频率 5.250025 = 1 + Math.log(19630 / (279+1))
            5.250025 = idf(docFreq=279, maxDocs=19630) 
            // 这里的queryNorm值是乘以了加权数的结果,如果只搜索一个词的情况则不会乘以加权数而是把加权数单独列出来
            // 0.11881979 = 3.9606597E-4 * 300
            0.11881979 = queryNorm 
          // 1.9687593 = 1.0 * 5.250025 * 0.375
          1.9687593 = fieldWeight in 16295, product of:
            // 词频参数,公式: Math.sqrt(termFreq)
            1.0 = tf(freq=1.0), with freq of: 
              // 查询词在当前文档的字段出现次数
              1.0 = termFreq=1.0 
            // 逆向文档频率 5.250025 = 1 + Math.log(19630 / (279+1))
            5.250025 = idf(docFreq=279, maxDocs=19630) 
            // 字段长度计算出来的值 0.37796447 = 1.0 / Math.sqrt(7),因为经度损失问题这里显示0.375
            0.375 = fieldNorm(doc=16295) 
      0.8139789 = weight(productName:休闲 in 16295) [DefaultSimilarity], result of: 
        0.8139789 = score(doc=16295,freq=1.0), product of: 
          0.5078499 = queryWeight, product of: 
            4.2741184 = idf(docFreq=742, maxDocs=19630) 
            0.11881979 = queryNorm 
          1.6027944 = fieldWeight in 16295, product of: 
            1.0 = tf(freq=1.0), with freq of: 
              1.0 = termFreq=1.0 
            4.2741184 = idf(docFreq=742, maxDocs=19630) 
            0.375 = fieldNorm(doc=16295) 
    // 0.18660358 = 0.37320715 * 0.5
    0.18660358 = product of: 
      0.37320715 = sum of: 
        0.37320715 = weight(labels:运动 in 16295) [DefaultSimilarity], result of: 
          0.37320715 = score(doc=16295,freq=1.0), product of: 
            0.21748722 = queryWeight, product of: 
              5.4911866 = idf(docFreq=219, maxDocs=19630) 
              // 同样这里也乘以加权数
              // 0.039606597 = 3.9606597E-4 * 100
              0.039606597 = queryNorm 
            1.7159958 = fieldWeight in 16295, product of: 
              1.0 = tf(freq=1.0), with freq of: 
                1.0 = termFreq=1.0 
              5.4911866 = idf(docFreq=219, maxDocs=19630) 
              0.3125 = fieldNorm(doc=16295) 
      // 因为商品关键字字段只匹配到了一个词,所以这里是0.5
      0.5 = coord(1/2) 
  // hasStock 1 代表库存,0代表无库存,此处是对有库存的商品做了加权
  // 0.5940989 = 1.0 * 1500.0 * 3.9606597E-4
  0.5940989 = FunctionQuery(sum(abs(int(hasStock)))), product of: 
    1.0 = sum(abs(int(hasStock)=1)) 
    1500.0 = boost 
    3.9606597E-4 = queryNorm


打分关键字段

参考文档:https://www.elastic.co/guide/cn/elasticsearch/guide/current/practical-scoring-function.html

docFreq    仅包含查询词的文档数量

maxDocs    全部文档数量

idf        逆向文档频率 ,根据匹配的文档数量以及总文档数量计算的一个值
计算公式: idf = 1 + Math.log(maxDocs / (docFreq+1))
例如本例中的idf的值为  5.250025 = 1 + Math.log(19630 / (279+1))

termFreq   查询词在当前字段中出现的次数,例如上例中“运动”在商品名称中只出现一次所以这个值是1

tf         词频,通过查询词出现在当前文档所在字段中的次数计算出的一个值.
计算公式: tf = Math.sqrt(termFreq)

queryNorm  根据查询词每次动态计算的一个固定值,不影响实际排序。

coord      字段包含被查询词的比例,如上面的labels只包含一个词则是0.5.

boost      加权数,一般是在查询时控制打分结果,如上面给商品名称加权300

fieldNorm  根据文档中字段内容拆词后的长度计算出的一个固定值,创建索引的时候就已经确定。
计算公式:fieldNorm = 1.0 / Math.sqrt(numTerms)
例如本例中的商品名拆词后长度为7则计算出的值为  0.37796447 = 1.0 / Math.sqrt(7)
注意:fieldNorm存储的时候会经过算法转成一个字节保存,所以会有精度的损失,这就是在上面显示的是0.375的原因


其他说明:

0.5940989 = FunctionQuery(sum(abs(int(hasStock)))), product of: 

前面的0.5940989 是计算出的评分值,后面的FunctionQuery(sum(abs(int(hasStock))))是计算公式,最后的product of:代表评分值是下面几项的分值相乘的出的

如 0.5940989 = 1.0 * 1500.0 * 3.9606597E-4


2.0421042 = sum of:  如果是sum of则是下面几项相加

如 2.0421042 = 1.2281255 + 0.8139789


2.0421042 = max of:  如果是max of则是取下面几项里面最大的那个值

如 2.0421042 是取的商品名称的评分值,商品关键字的评分则被忽略


详细分析打分结果

2.6362033 = sum of:  最终计算的总得分


提交评论