ps:临时写的,大体的实现和简单版, 以后会不断完善 博客和 代码

github:https://github.com/Eric-ly/solr_engine

solr是基于lucene的全文检索 搜索引擎,和一般查数据库相比,solr的一个特色就是它的相关度评分。 这里介绍一下它的自定义 相关度评分。

solr的评分是需要考虑很多因素的 有一个公式,比如会考虑 一句话中 关键字出现的频率,一片文章中关键字出现的频率和这篇文章的长度 来综合计算相关度评分。

在实际的业务中,可能不需要这么复杂的相关度,是需要简单粗暴的 按照我指定的规则计算相关度,并按照相关度进行排序。使用默认的话 因为因素过多 (比如分数小数太多) 可能不能让评分按照我自己的方式计算(最后分数)即最后的分数会有差别。

需求问题,比如:

我只想要 滑雪 加10分 然后我根据标题包含滑雪的排序

1.标题 含滑雪 > 标题 不含 滑雪

2.正文含滑雪 >正文不含滑雪

3.文章的质量分 高大于 低

这个时候如果用默认的 我无法 在滑雪中根据正文包含 或者 质量分进行二层,三层排序, 因为 条件1 (标题中包含 滑雪关键字的 )的评分 就不一样 导致 排序结果 从一开始就是错误的

所以我需要一个按照我自己定义的规则计算的相关度评分。

这里我大概介绍一下 如何自定义自己的相关度评分

solr使用的默认相关度是 DefaultSimilarity 类,

1.这里我们重写DefaultSimilarityFactory , 获取自定义的similarity

public class BootSimilarityFactory extends SimilarityFactory {
    @Override
    public Similarity getSimilarity(){
        return new  BootSimilarity();
    }
}
复制代码

2.BootSimilarity 中simScorer方法 只是用很少的 因素

    @Override
    public SimScorer simScorer(SimWeight weight, LeafReaderContext context) throws IOException {
        BoostSimWeight boostSimWeight = (BoostSimWeight)weight;
        return new BoostSimScorer(boostSimWeight);
    }
复制代码

BootSimScorer 方法,这里我们可以看到explain 方法 我只是使用了boostSimWeight.boost 分数,而对比 默认方法我们就会发现

    public class BoostSimScorer extends SimScorer{

略
        @Override
        public Explanation explain(int doc, Explanation freq) {
            return Explanation.match(
                    boostSimWeight.boost,
                    "(boost is:" + boostSimWeight.boost + " )",
                    Collections.singleton(freq));
        }

略
    }
复制代码

如下是默认的评分:

DefaultSimilarity 继承TFIDFSimilarity 类,具体方法由TFIDFSimilarity实现。

TFIDFSimilarity 类:
    public final SimWeight computeWeight(float queryBoost, CollectionStatistics collectionStats, TermStatistics... termStats) {
        Explanation idf = termStats.length == 1 ? this.idfExplain(collectionStats, termStats[0]) : this.idfExplain(collectionStats, termStats);
        return new TFIDFSimilarity.IDFStats(collectionStats.field(), idf, queryBoost);
    }
复制代码

其中的内部类simScore的explain方法

private final class TFIDFSimScorer extends SimScorer {
略
 public Explanation explain(int doc, Explanation freq) {
      return TFIDFSimilarity.this.explainScore(doc, freq, this.stats, this.norms);
 }
复制代码

这个方法太长 我就给大家截图展示下。

大家会发现这里面有很多的计算方法。

加之前的效果图片:

加完之后的效果图片

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐