薯拾

solr-similarity

2019-06-16

评分公式

Solr采用了最基本的向量空间模型:
solrsimilarity.png

  •  t = term, d = document, q = query , f = field
  •  tf(t in d ) 表示该term 在 这个文档里出现的频率(即出现了几次)。
    $$tf(t in d) = numTermOccurrencesInDocument^{1/2}$$
  •  idf(t) 表示 出现该term的文档个数。
    $$idf(t) = 1 + log (numDocs / (docFreq +1))$$
  •  t.getBoost() 查询语句中每个词的权重,可以在查询中设定某个词更加重要。
    1
    2
    3
    title:(solr in action)^2.5  //对solr in action 这个pharse设置boost
    title:(solr in action) // 默认的boost时1.0
    title:(solr^2in^.01action^1.5)^3OR"solrinaction"^2.5
  •  norm(t,d) 标准化因子d.getBoost() • lengthNorm(f) • f.getBoost() ,它包括三个参数:
    • Document boost:此值越大,说明此文档越重要。对document设置boost是通过对每一个field设置boost实现的
    • Field boost:此域越大,说明此域越重要。
    • lengthNorm(field) = (1.0 / Math.sqrt(numTerms)):一个域中包含的Term总数越多,也即文档越长,此值越小,文档越短,此值越大。
      $$norm(t,d) = d.getBoost() • lengthNorm(f) • f.getBoost()$$
  • coord(q,d):一次搜索可能包含多个搜索词,而一篇文档中也可能包含多个搜索词,此项表示,当一篇文档中包含的搜索词越多,则此文档则打分越高 .
    $$coord(q,d)=numTermsInDocumentFromQuery / numTermsInQuery $$
  • queryNorm(q):计算每个查询条目的方差和,此值并不影响排序,而仅仅使得不同的query之间的分数可以比较。
    $$queryNorm(q) = 1 / (sumOfSquaredWeights )$$
    $$sumOfSquaredWeights = q.getBoost()2 • ∑ ( idf(t) • t.getBoost() )2$$

每个fieldType配置单独的similarity

项目中有两个需求:

  • filed1 搜索时返回满足搜索条件的,热度最高的记录;
  • filed2 存储我们对记录的机器学习标签,每一个标签有一个置信度,希望返回满足搜索需要的标签的前提下置信度更高的;

针对以上需求,显然不能使用全局配置一个similarity的计算方法,不同的filed采用不同的策略。因此定义了两个对应的filedType。

对于第一个需求,采用继承TFIDFSimilarity类的方式封装实现自己的jar包,并配置使用,也就是这里的CustomSimilarity,以及对应的Factory。在自定义的相似度中,通过将tf,idf等值设置为固定值,这样原有的相似度计算方式对结果的影响就小了,再通过存储在score这个filed中的值排序,在查询时增加参数 &sort=score desc。

1
2
3
4
5
6
7
8
9
10
package com.*.*;
public float coord(int overlap, int maxOverlap) {return 1.0F;}
public float queryNorm(float sumOfSquaredWeights) {return 1.0F;}
public float tf(float paramFloat) {return 1.0F;}
public float tf(int param) { return 1.0F;}
public float idf(long numDocs, long docFreq) {return 1.0F;}
public float lengthNorm(FieldInvertState state) {return 1.0F;}
public float sloppyFreq(int paramInt) {return 1.0F;}
public float scorePayload(int paramInt1, int paramInt2, int paramInt3, BytesRef paramBytesRef) {return 1.0F;}
......
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?xml version="1.0" encoding="UTF-8" ?>
<schema name="example" version="1.5">
<fieldType name="text_1" class="solr.TextField" positionIncrementGap="0">
<similarity class="com.**.**.CustomSimilarity"/>
...
...
</fieldType>

<fieldType name="text_2" class="solr.TextField" positionIncrementGap="0" omitNorms="true">
...
...
</fieldType>
...
...
<similarity class="solr.SchemaSimilarityFactory"/>
</schema>

针对第二个需求,通过配置 omitNorms=”true”,忽略长度的正则项,也就是忽略前面的lengthNorm,因此第二个需求可以通过重复不同次数的标签来实现满足标签的条件下,高置信度的搜索。

  • omitNorms
    如果为true,则忽略与此字段关联的正则(这将禁用字段的长度正则,并节省一些内存)。 对于所有原始字段类型,例如int,float,data,bool和string,默认为true。 只有全文字段或字段才需要正则。

Reference

https://www.cnblogs.com/rcfeng/p/4067896.html
https://lucene.apache.org/solr/guide/6_6/field-type-definitions-and-properties.html

Tags: solr
使用支付宝打赏
使用微信打赏

若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏

扫描二维码,分享此文章