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);
}
複製程式碼