過濾集提升權重
回到 忽略 TF/IDF 裏處理過的問題,我們希望根據每個度假屋的特性數量來評分, 當時我們希望能用緩存的過濾器來影響評分,現在 function_score
查詢正好可以完成這件事情。
到目前爲止,我們展現的都是爲所有文檔應用單個函數的使用方式,現在會用過濾器將結果劃分爲多個子集(每個特性一個過濾器),併爲每個子集使用不同的函數。
functions是一個數組,裡面放著的是將要被使用的加強函數列表,我們在裡面使用了3個filter去過濾數據,並且每個filter都設置了一個加強函數,並且還使用了一個會應用到所有文檔的field_value_factor加強函數
可以爲列表裡的每個加強函數都指定一個filter,這樣做的話,只有在文檔滿足此filter的要求,此filter的加強函數纔會應用到文擋上,也可以不指定filter,這樣的話此加強函數就會應用到全部的文擋上
一個文檔可以一次滿足多條加強函數和多個filter,如果一次滿足多個,那麼就會產生多個加強score
因此ES會先使用score_mode定義的方式來合併這些加強score們,得到一個總加強score,得到總加強score之後,纔會再使用boost_mode定義的方式去和old_score做合併
GET 127.0.0.1/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合併
}
}
}
過濾 vs. 查詢
首先要注意的是 filter
過濾器代替了 query
查詢, 在本例中,我們無須使用全文搜索,只想找到 city
字段中包含 Barcelona
的所有文檔,邏輯用過濾比用查詢表達更清晰。過濾器返回的所有文檔的評分 _score
的值爲 1
。 function_score
查詢接受 query
或 filter
,如果沒有特別指定,則默認使用 match_all
查詢。
評分模式 score_mode
每個函數返回一個結果,所以需要一種將多個結果縮減到單個值的方式,然後才能將其與原始評分 _score
合併。評分模式 score_mode
參數正好扮演這樣的角色, 它接受以下值:
multiply
函數結果求積(默認)。
sum
函數結果求和。
avg
函數結果的平均值。
max
函數結果的最大值。
min
函數結果的最小值。
first
使用首個函數(可以有過濾器,也可能沒有)的結果作爲最終結果
在本例中,我們將每個過濾器匹配結果的權重 weight
求和,並將其作爲最終評分結果,所以會使用 sum
評分模式。
不與任何過濾器匹配的文檔會保有其原始評分, _score
值的爲 1
。
其實weight加強函數也是可以不和filter搭配,自己單獨使用的,只是這樣做沒啥意義,因爲只是會給全部的文檔都增加一個固定值而已
-
不過就DSL語法上來說,他也像其他加強函數一樣,是可以直接使用而不用加filte
GET 127.0.0.1/mytest/doc/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
}
},
functions: [
{
"weight": 3
}
]
}
}