1. 程式人生 > >關於elasticsearch function_score的使用

關於elasticsearch function_score的使用

    最近做新聞推薦系統,新聞搜尋採用的是elasticsearch引擎,為了使推薦更接近使用者偏好,搜尋時使用了function_score功能對文件進行了重新打分,改變排序規則。以下介紹關於function score的一些用法。

     The function_score allows you to modify the score of documents that are retrieved by a query. This can be useful if, for example, a score function is computationally expensive and it is sufficient to compute the score on a filtered set of documents.(這個是官方對function_score的解釋)

   es內建了幾種預先定義好了的函式:

      1、weight:對每份文件適用一個簡單的提升,且該提升不會被歸約:當weight為2時,結果為2 * _score。

      2、field_value_factor:使用文件中某個欄位的值來改變_score,比如將受歡迎程度或者投票數量考慮在內。

      3、random_score:使用一致性隨機分值計算來對每個使用者採用不同的結果排序方式,對相同使用者仍然使用相同的排序方式。

      4、Decay Functions:衰減函式,衰減函式是利用從給定的原點到某個使用者數字型別欄位的值的距離的衰減進行打分的。這類似於一個範圍查詢,而且邊緣是光滑的。

      es內部支援的衰減函式有gauss(高斯)、exp(指數)、linear(線性)

      5、 script_score:使用自定義的指令碼來完全控制分值計算邏輯。

    推薦系統中有很多個性化的feature權重,所以我們主要採用script_score來對文件打分。下面主要說一下script_score的使用。

(1)、在es配置中配置指令碼功能,配置後重啟服務

script.inline: on

script.enfine.groovy.inline.aggs: on

script.indexed: on

script.file: on

    (2)、測試查詢語句,例:

 

{
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "should": [
            {
              "match": {
                "title": "航母"
              }
            }
          ]
        }
      },
      "score_mode": "first",
      "script_score": {
        "lang": "groovy",
        "params": {
          "timestamp": 1460768418541
        },
        "script": "(_score+ 1/(timestamp-doc['timestamp'].value.toDouble()+1))/2"
      },
      "boost_mode": "replace"
    }
  }
}     
  •   查詢結果中可以看到每條文件資料的分值  例:"_score"0.5103256,
  • (3)、java查詢程式碼  queryBuilder:
  • Map<String,Object> params = new HashMap<String,Object>();
    params.put("timestamp",1460768428541L);
    FunctionScoreQueryBuilder query = 
        QueryBuilders.functionScoreQuery(QueryBuilders.boolQuery()
            .should(QueryBuilders.matchQuery("title", "航母"))
        ).add(ScoreFunctionBuilders.scriptFunction(
            new Script("(_score + 1/(timestamp-doc['timestamp'].value.toDouble()+1))/2"
                ,ScriptType.INLINE,"groovy",params))
        ).scoreMode("first")
        .boostMode(CombineFunction.REPLACE);

  •     "script_score": {
            "lang": "groovy",
            "params": {
              "timestamp": 1460768418541
            },
            "script": "(_score+ 1/(timestamp-doc['timestamp'].value.toDouble()+1))/2"
          },
  •      以上這部分就是指令碼函式打分的一個實現。lang表示選用的指令碼語言,這裡我們選用groovy(es配置,預設groovy);params是指令碼函式需要的引數;script是函式語句(參照groovy語法)