Elasticsearch – 二次打分處理方案


有時ES默認的評分規則並不能滿足需求,時長會有在old_source的基礎上根據某字段的值需要重新打分的需求場景,比如在相關度相差不大的情況下時間越進越靠前,或者評論數越多越靠前等等。此時需要重新打分。對此可以通過兩種方式法來處理:

1、在創建索引的時候提高文檔的權重,根據因素字段值來給文檔設置boost.這種方式在lucene之前有效,之后就無效了。不建議采用。

2、通過function_query來設置分數。

通過function_query來設置分數

線性提升

如在相關度相差不大的情況下,投票的數量越多排名越往前。可以采用簡單的線性方式來處理:

GET /blogposts/post/_search  
{  
  "query": {  
    "function_score": {  
      "query": {  
        "multi_match": {  
          "query":    "popularity",  
          "fields": [ "title", "content" ]  
        }  
      },  
      "field_value_factor": {  
        "field":    "votes",  
        "modifier": "log1p",  
        "factor":   2   
      }  
    }  
  }  
}  

其中:

  • field:表示影響權重的字段例子中是votes
  • modifier:表示影響的規則
  • 修飾語 modifier 的值可以為:
    none (默認狀態)
    log 、 log1p 、 log2p 、 ln 、 ln1p 、 ln2p 、 square 、 sqrt 以及 reciprocal。
    facror:表示影響因子。
    通過上面設置后整個打分變為:
new_score = old_score * log(1 + factor * number_of_votes)  
factor 值大於 1 會提升效果, factor 值小於 1 會降低效果。  

初次之外還可以設置boost_mode影響因子和old_source通過什么運算來得出新分值。

GET /blogposts/post/_search  
{  
  "query": {  
    "function_score": {  
      "query": {  
        "multi_match": {  
          "query":    "popularity",  
          "fields": [ "title", "content" ]  
       }  
      },  
      "field_value_factor": {  
        "field":    "votes",  
        "modifier": "log1p",  
        "factor":   0.1  
      },  
      "boost_mode": "sum" ,  
      "max_boost":  1.5   
    }  
  }  
}  

boost_mode
multiply評分 _score 與函數值的積(默認)
sum評分 _score 與函數值的和
min評分 _score 與函數值間的較小值
max評分 _score 與函數值間的較大值
replace函數值替代評分 _scoremax_boost設置最大的得分分值
無論 field_value_factor 函數的結果如何,最終結果都不會大於 1.5

引入模型函數來控制二次評分

上線是一種線性的影響關系,有時會有范圍性質、分數變化緩慢的需求場景,此時在使用上面的方案未免為使分數變化的不太圓滑,es提供了三種衰減函數(decay functions)來計算分數,讓我們有能力在兩個滑動標准如:地點和價格,時間等之間權衡。

   linear、 exp 和 gauss (線性、指數和高斯函數),它們可以操作數值、時間以及經緯度地理坐標點這樣的字段。所有三個函數都能接受以下參數:

origin:中心點 或字段可能的最佳值,落在原點 origin 上的文檔評分 _score 為滿分 1.0 。
scale:衰減率,即一個文檔從原點origin下落時,評分_score 改變的速度.(例如,每 £10 歐元或每 100 米)
decay:從原點 origin 衰減到 scale 所得的評分 _score ,默認值為 0.5 。
offset:以原點 origin 為中心點,為其設置一個非零的偏移量 offset 覆蓋一個范圍,而不只是單個原點。在范圍 -offset <= origin <= +offset 內的所有評分 _score 都是 1.0 。
這三個函數的唯一區別就是它們衰減曲線的形狀,用圖來說明會更為直觀

圖 33 “衰減函數曲線” 中所有曲線的原點 origin (即中心點)的值都是 40 , offset 是 5 ,也就是在范圍 40 - 5 <= value <= 40 + 5 內的所有值都會被當作原點 origin 處理——所有這些點的評分都是滿分 1.0 。

在此范圍之外,評分開始衰減,衰減率由 scale 值(此例中的值為 5 )和 衰減值 decay (此例中為默認值 0.5 )共同決定。結果是所有三個曲線在 origin +/- (offset + scale) 處的評分都是 0.5 ,即點 30和 50 處。

linear 、 exp 和 gauss (線性、指數和高斯)函數三者之間的區別在於范圍( origin +/- (offset + scale) )之外的曲線形狀:

linear 線性函數是條直線,一旦直線與橫軸 0 相交,所有其他值的評分都是 0.0 。
exp 指數函數是先劇烈衰減然后變緩。
gauss 高斯函數是鍾形的——它的衰減速率是先緩慢,然后變快,最后又放緩。
選擇曲線的依據完全由期望評分 _score 的衰減速率來決定,即距原點 origin 的值。

回到我們的例子:用戶希望租一個離倫敦市中心近( { "lat": 51.50, "lon": 0.12} )且每晚不超過 £100 英鎊的度假屋,而且與距離相比, 我們的用戶對價格更為敏感,這樣查詢可以寫成:

{  
    "query": {  
        "function_score": {  
          "functions": [  
            {  
              "gauss": {  
                "price": {  
                  "origin": "0",  
                  "scale": "20"  
                }  
              }  
            },  
            {  
              "gauss": {  
                "location": {  
                  "origin": "11, 12",  
                  "scale": "2km"  
                }  
              }  
            }  
          ],  
          "query": {  
            "match": {  
              "properties": "balcony"  
            }  
          },  
          "score_mode": "multiply"  
        }  
    }  
}  

location 字段以地理坐標點 geo_point 映射。
price 字段是數值。
price 語句是 location 語句權重的兩倍。
location 語句可以簡單理解為:
以倫敦市中作為原點 origin 。
所有距原點 origin 2km 范圍內的位置的評分是 1.0 。
距中心 5km ( offset + scale )的位置的評分是 0.5 。

weight 參數可以被用來調整每個語句的貢獻度,權重 weight 的默認值是 1.0 。這個值會先與每個句子的評分相乘,然后再通過 score_mode 的設置方式合並。

參考資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM