ES評分這一塊主要依靠function_score
,它可以改變查詢返回文檔的分數。通常計算得分代價比較大,它可以對已經過濾的文檔進行評分。function_score
中需要定義一個 query 以及一個或多個計算查詢的得到文檔得分的函數。只有一個計算得分函數的示例如下:
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
// random_score 就是一種隨機計算得分的函數
"random_score": {},
"boost_mode":"multiply"
}
}
}
在function_score
中提供幾種計算得分的函數:
script_score
:可以在內部包裹額外的query語句,可以選擇使用文檔中其他數字屬性值來計算自定義評分;weight
:可以將得分和weight
字段值相乘,有時可能會希望這樣做,因爲對特定查詢設置的提升值(即boost
設置的值)進行了歸一化,而對於此得分函數卻沒有,數字值是float類型;random_score
:根據_uid
的hash值生成得分,並帶有一個變化的seed
,如果不指定seed
的值,則使用當前時間戳;field_value_factor
:可以使用文檔中的字段來人爲影響得分,和script_score
函數相似,但它可以避免腳本開銷。如果被用於一個多值字段,那只有該字段的第一個值會被用來計算,其他的值不會用於計算;- decay functions:衰減函數,可以隨着文檔距離給定值(數值類型,表示原點)的距離進行評分,需要指定參與評分的每個字段的
origin
(標識中心值)和scale
(衰減的速率)。
下面的是示例文檔結構:
"_source": {
"id": 1724933159515744,
"propertyId": 1724930759808608,
"name": "測試文檔",
"categoryIds": [
10000046,
10000001,
10000000
],
"subject": null,
"status": -1,
"description": "這僅僅是一個測試評分的文檔",
"shopId": 1587726129258720
}
以上面的文檔爲示例,腳本如下:
// 1. script_score 函數計算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
"query": {
"match": {
"name": "門"
}
},
"boost": "1",
"script_score": {
"script": {
// 這個字段主要用於自定義變量,有必要的話需要定義
"params": {
"paramA": 2,
"paramB": 10
},
// 使用文檔中各自 status 字段的平方作爲評分
"inline": "Math.pow(doc['status'].value, params.paramA) + params.paramB"
}
}
}
}
}
// 2. weight 函數計算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
"query": {
"match": {
"name": "門"
}
},
"boost": "1",
// 可以調整該參數大小觀察最終得分的變化
"weight": 2
}
}
}
// 3. random_score 函數計算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
// random_score 就是一種隨機計算得分的函數,使用 _uid 的hash值打分,攜帶一個 seed 變量
"random_score": {},
"boost_mode":"multiply"
}
}
}
// 4. field_value_factor 函數計算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
// 使用 字段值 影響打分,最終得分爲 sqrt(1.2 * doc['categoryIds'].value)
"field_value_factor": {
// categoryIds 是一個數組,取數組中的第一個值進行計算
"field": "categoryIds",
// 影響因子
"factor": 1.2,
// 計算方式選擇開根號
"modifier": "sqrt",
"missing": 1
},
"boost": "1"
}
}
}
// 5. 衰減函數 計算得分
GET localhost:9200/index-name/_search?pretty
{
"query": {
"function_score": {
// 選用高斯(還有線性和)衰減函數
"gauss": {
"status": {
"origin": 80,
"scale": 5,
"offset": 1,
"decay" : 0.5
}
}
}
}
}
注:
1.field_value_factor
函數中
field
:從文檔中提取出來參與計算評分的字段;factor
:(可選),標識從文檔中提取字段的影響因子,默認爲1;modifier
:用於提取的字段如何參與評分,可選行爲有:none
:不對該字段做任何評分行爲(默認);log
:使用 log 進行對數計算,取10爲底;log1p
:對提取的字段加1後取對數,取10爲底;log2p
:同上,加2取對數,取10爲底;ln
:同上,取 e 爲底;ln1p
:同上,加1並取 e 爲底;ln2p
:同上,加2並取 e 爲底;square
:直接平方;sqrt
:開根號;reciprocal
:取倒數
missing
:如果提取的字段在文檔中不存在,則使用missing
提供的值替代field
指定的字段值進行計算;
上述modifier
的幾種行爲務必注意一些算術異常,比如log
和ln
以及reciprocal
函數不能對0進行計算,如果出現就會出現算術異常,可以適當使用log1p
來替換使用或者直接過濾掉這部分爲0的數據。
2.衰減函數Decay functions中
- 衰減函數:本身包含線性(
linear
)、指數(exp
)、高斯(gauss
)三種衰減函數可選; origin
:表示給定的中心值,即原點,必須和提取的字段本身類型一致,如上述類型提取文檔的status
字段爲數值類型,那原點也必須爲數值,對於Date類型的字段支持使用now
作爲變量使用;scale
:表示衰減函數的衰減速率,其實origin
+offset
=decay
。對於地理類型geo
可以定義爲數值+單位
的形式(如2m
、5km
,默認單位爲m
),對於Date
類型,可以定義爲1h
、2d
等等形式(默認單位爲毫秒);offset
:可選參數,如果定義了該參數,衰減函數將會只計算那些離原點origin
的距離大於該值的文檔進行評分,默認爲0;decay
:定義了衰減函數如何按比例給定的距離對文檔進行評分,如果未定義decay
,則距離標尺上的文檔將獲得0.5分。
關於具體的使用參見文檔Supported decay functions。