过滤集提升权重
回到 忽略 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搭配,自己单独使用的,只是这样做没啥意义,因为只是会给全部的文档都增加一个固定值而已
GET 127.0.0.1/mytest/doc/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
}
},
functions: [
{
"weight": 3
}
]
}
}