设为首页 收藏本站
查看: 1367|回复: 0

[经验分享] solr 评分机制

[复制链接]
发表于 2016-12-16 06:22:03 | 显示全部楼层 |阅读模式
转自 http://blog.chenlb.com/2009/08/lucene-scoring-architecture.html
 
Lucene 评分体系/机制(lucene scoring)是 Lucene 出名的一核心部分。它对用户来说隐藏了很多复杂的细节,致使用户可以简单地使用 lucene。但个人觉得:如果要根据自己的应用调节评分(或结构排序),十分有必须深入了解 lucene 的评分机制。
Lucene scoring 组合使用了 信息检索的向量空间模型 和 布尔模型 。
首先来看下 lucene 的评分公式(在 Similarity 类里的说明)
score(q,d)   =   coord(q,d) ·  queryNorm(q) ·( tf(t in d) ·  idf(t)2 ·  t.getBoost() ·  norm(t,d) )
 t in q 
其中:

  • tf(t in d) 关联到项频率,项频率是指  t 在 文档 d 中出现的次数 frequency。默认的实现是:
    tf(t in d) =frequency½

  • idf(t) 关联到反转文档频率,文档频率指出现  t 的文档数 docFreq。docFreq 越少 idf 就越高(物以稀为贵),但在同一个查询下些值是相同的。默认实现:
    idf(t) =1 + log (
    numDocs
    –––––––––
    docFreq+1
    )

  • coord(q,d) 评分因子,是基于文档中出现查询项的个数。越多的查询项在一个文档中,说明些文档的匹配程序越高。默认是出现查询项的百分比。
  • queryNorm(q)查询的标准查询,使不同查询之间可以比较。此因子不影响文档的排序,因为所有有文档都会使用此因子。默认值:
    queryNorm(q)   =   queryNorm(sumOfSquaredWeights) =
    1
    ––––––––––––––
    sumOfSquaredWeights½ 

     
    每个查询项权重的平分方和(sumOfSquaredWeights)由 Weight 类完成。例如 BooleanQuery 地计算:
    sumOfSquaredWeights =   q.getBoost() 2 ·( idf(t) ·  t.getBoost() ) 2
     t in q

  • t.getBoost()查询时期的 项 t 加权(如:java^1.2),或者由程序使用 setBoost()。
  • norm(t,d)压缩几个索引期间的加权和长度因子:

    • Document boost - 文档加权,在索引之前使用 doc.setBoost()
    • Field boost - 字段加权,也在索引之前调用 field.setBoost()
    • lengthNorm(field) - 由字段内的 Token 的个数来计算此值,字段越短,评分越高,在做索引的时候由 Similarity.lengthNorm 计算。
    以上所有因子相乘得出 norm 值,如果文档中有相同的字段,它们的加权也会相乘: 
    norm(t,d)   =   doc.getBoost() ·  lengthNorm(field) ·f.getBoost()
     field f in d named as t 
    索引的时候,把 norm 值压缩(encode)成一个 byte 保存在索引中。搜索的时候再把索引中 norm 值解压(decode)成一个 float 值,这个 encode/decode 由 Similarity 提供。官方说:这个过程由于精度问题,以至不是可逆的,如:decode(encode(0.89)) = 0.75。
计算这个评分涉及到几个核心的类/接口:Similarity、Query、Weight、Scorer、Searcher,由它们或其子类来完成评分的计算。先来看下它们的类图:

DSC0000.jpg lucene search score uml, 点击放大

搜索中,评分的过程:

  • 创建一个查询对象 Query,传给 Searcher,具体来讲可能是 IndexSearcher。
  • Searcher 根据 Query 创建一个对应的 Weight(是 Query 的内部特征表示),接着 Weight 会创建对应的 Scorer。
  • Searcher 会创建 Hitcollector 并传到 Scorer,scorer 找到匹配的文档并计算评分,最后写到 Hitcollector 中。
Query、Weight、Scorer 三都关系十分密切,尤其是 Query 和 Weight。Weight 是计算查询权重和创建 Scorer 的。Query 为了可以重用把内部的特征抽象为 Weight,由子类去完成一些相关评分的计算。
任何 Searcher 依赖的状态都存储在 Weight 实现中,而不是在Query 中,这样可以重用 Query。
Weight 的生命周期(被使用):

  • Weight 由顶层的 Query 创建。Query.createWeight(Searcher),创建的 Weight 给 Searcher 去使用。
  • 当用 Similarity.queryNorm(float) 来计算查询标准化因子(query normalization)的时候,Weight.sumOfSquaredWeights() 会被调用。
  • 查询标准化因子(query normalization)会传给 Weight.normalize(float)计算,这个时候权重(weighting)计算完成。
  • 创建一个 Scorer。
自定义评分的计算
可以实现一个 Similarity 换掉默认的。它仅限于 Scorer、Weight 计算好的因子值再加工。要想对评分有更强的控制力,可以实现一套 Query、Weight、Scorer。

  • Query 是用户信息需要的抽象
  • Weight 是 Query 的内部特性表示的抽象
  • Scorer 抽象公用的计算评分功能,提供计算评分和解说(explanation)评分的能力。
Query 子类实现的方法:

  • createWeight(Searcher searcher) -- Weight 是 Query 内部代表,所以每个 Query 都必实现一个 Weight,此方法就是生成一个Query对应的Weight对象。
  • rewrite(IndexReader reader) -- 重写查询为原始的查询,原始的查询有:TermQuery,BooleanQuery……
Weight 接口方法:

  • Weight#getQuery() -- 指出代表 Weight 的 Query。
  • Weight#getValue() -- Query 的权重,例如:TermQuery.TermWeight 的 value = idf^2 * boost * queryNorm
  • Weight#sumOfSquaredWeights() -- 各查询项的平方和,如,TermWeight 的 = (idf * boost)^2
  • Weight#normalize(float) -- 决定查询标准化的因子,查询标准化值可以在不同 Query 比较 score
  • Weight#scorer(IndexReader) -- 创建 Query 对应的评分器 Scorer,它的责任是给 Query 匹配到的文档评分。
  • Weight#explain(IndexReader, int) -- 给指定的文档详细解说评分值是怎么得来了。
Scorer 子类实现的方法:

  • Scorer#next() -- 预取匹配到的下一文档,有才返回 true。
  • Scorer#doc() -- 返回当前匹配到的文档id,它必须 next() 调用后才有效。
  • Scorer#score() -- 返回当前文档的评分,此值可以由应用程序以任何适当的方式给出,如 TermScorer 返回 tf * Weight.getValue() * fieldNorm
  • Scorer#skipTo(int) -- 跳到大于或等于 int 的匹配文档上。很多情况下,在结果集中 skipTo 比较循环更加快速高效。
  • Scorer#explain(int) -- 给出评分产生的细节。
要实现一套 Query、Weight、Scorer,最好还是看下 TermQuery、TermWeight、TermScorer。
当 Lucene 中没有想要的查询时(包括不同的评分细节),自定义Query 可能帮得上忙。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-314773-1-1.html 上篇帖子: Solr Dismax Handler 下篇帖子: solr repliaction机制
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表