閱讀本文需要先了解 function_score 的相關知識,請看 ElasticSearch - function_score 簡介
一樣先準備數據和索引,在 ES 插入三筆數據,其中 language 是 keyword 類型,like 是 integer 類型(代表點贊量)
{ "language": "java", "like": 5 }
{ "language": "python", "like": 5 }
{ "language": "go", "like": 10 }
functions 是一個數組,裡面放著的是將要被使用的加強函數列表,我們在裡面使用了 3 個 filter 去過濾數據,並且每個 filter 都設置了一個加強函數,並且還使用了一個會應用到所有文檔的 field_value_factor 加強函數
可以為列表裡的每個加強函數都指定一個 filter,這樣做的話,只有在文檔滿足此 filter 的要求,此 filter 的加強函數才會應用到文擋上,也可以不指定 filter,這樣的話此加強函數就會應用到全部的文擋上
一個文檔可以一次滿足多條加強函數和多個 filter,如果一次滿足多個,那麼就會產生多個加強 score
因此 ES 會先使用 score_mode 定義的方式來合併這些加強 score 們,得到一個總加強 score,得到總加強 score之後,才會再使用 boost_mode 定義的方式去和 old_score 做合併
GET mytest/doc/_search
{
"query": {
"function_score": {
"query": {
"match_all": {} //match_all查出來的所有文檔的_score都是1
},
"functions": [
//第一個filter(使用weight加強函數),如果language是java,加強score就是2
{
"filter": {
"term": {
"language": "java"
}
},
"weight": 2
},
//第二個filter(使用weight加強函數),如果language是go,加強score就是3
{
"filter": {
"term": {
"language": "go"
}
},
"weight": 3
},
//第三個filter(使用weight加強函數),如果like數大於等於10,加強score就是5
{
"filter": {
"range": {
"like": {
"gte": 10
}
}
},
"weight": 5
},
//field_value_factor加強函數,會應用到所有文檔上,加強score就是like值
{
"field_value_factor": {
"field": "like"
}
}
],
"score_mode": "multiply", //設置functions裡面的加強score們怎麼合併成一個總加強score
"boost_mode": "multiply" //設置old_score怎麼和總加強score合併
}
}
}
"hits": [
{
//go同時滿足filter2、filter3
//且還有一個加強函數field_value_factor產生的加強
//因此加強score為3, 5, 10,總加強score為3*5*10=150
"_score": 150,
"_source": { "language": "go", "like": 10 }
},
{
//java只滿足filter1
//但是因為還有field_value_facotr產生的加強score
//因此加強score為2, 5,總加強score為2*5=10
"_score": 10,
"_source": { "language": "java", "like": 5 }
},
{
//python不滿足任何filter
//因此加強score只有field_value_factor的like值
//就是5
"_score": 5,
"_source": { "language": "python", "like": 5 }
}
]
其實 weight 加強函數也是可以不和 filter 搭配,自己單獨使用的,只是這樣做沒啥意義,因為只是會給全部的文檔都增加一個固定值而已
不過就 DSL 語法上來說,他也像其他加強函數一樣,是可以直接使用而不用加 filter 的
GET mytest/doc/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
}
},
functions: [
{
"weight": 3
}
]
}
}
"hits": [
{
"_score": 3,
"_source": { "language": "go", "like": 10 }
},
{
"_score": 3,
"_source": { "language": "python", "like": 5 }
},
{
"_score": 3,
"_source": { "language": "java", "like": 5 }
}
]
weight 加強函數也可以用來調整每個語句的貢獻度,權重 weight 的默認值是 1.0,當設置了 weight,這個 weight 值會先和自己那個 {}
裡的每個句子的評分相乘,之後再通過 score_mode 和其他加強函數合併
下面的查詢,公式為 new_score = old_score * [ (like值 * weight1) + weight2 ]
公式解析 : weight1 先加強 like 值(只能使用乘法),接著再透過 score_mode 定義的方法(sum)和另一個加強函數 weight2 合併,得到一個總加強 score,最後再使用 boost_mode 定義的方法(默認是 multiply)和 old_score 做合併,得到 new_score
GET mytest/doc/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
}
},
functions: [
{
"field_value_factor": {
"field": "like"
},
"weight": 3 //weight1, 加強field_value_factor,只能使用乘法,無法改變
},
{
"weight": 20 //weight2
}
],
"score_mode": "sum"
}
}
"hits": [
{
"_score": 50,
"_source": { "language": "go", "like": 10 }
},
{
"_score": 35,
"_source": { "language": "python", "like": 5 }
},
{
"_score": 35,
"_source": { "language": "java", "like": 5 }
}
]