过滤集提升权重

回到 忽略 TF/IDF 里处理过的问题,我们希望根据每个度假屋的特性数量来评分,当时我们希望能用缓存的过滤器来影响评分,现在 function_score 查询正好可以完成这件事情。

到目前为止,我们展现的都是为所有文档应用单个函数的使用方式,现在会用过滤器将结果划分为多个子集(每个特性一个过滤器),并为每个子集使用不同的函数。

在下面例子中,我们会使用 weight 函数,它与 boost 参数类似可以用于任何查询。有一点区别是 weight 没有被 Luence 归一化成难以理解的浮点数,而是直接被应用。

查询的结构需要做相应变更以整合多个函数:

  1. GET /_search
  2. {
  3. "query": {
  4. "function_score": {
  5. "filter": { (1)
  6. "term": { "city": "Barcelona" }
  7. },
  8. "functions": [ (2)
  9. {
  10. "filter": { "term": { "features": "wifi" }}, (3)
  11. "weight": 1
  12. },
  13. {
  14. "filter": { "term": { "features": "garden" }}, (3)
  15. "weight": 1
  16. },
  17. {
  18. "filter": { "term": { "features": "pool" }}, (3)
  19. "weight": 2 (4)
  20. }
  21. ],
  22. "score_mode": "sum", (5)
  23. }
  24. }
  25. }

<1> function_score 查询有个 filter 过滤器而不是 query 查询。

<2> functions 关键字存储着一个将被应用的函数列表。

<3> 函数会被应用于和 filter 过滤器(可选的)匹配的文档。

<4> pool 比其他特性更重要,所以它有更高 weight

<5> score_mode 指定各个函数的值进行组合运算的方式。

这个新特性需要注意的地方会在以下小节介绍。

过滤 vs. 查询

首先要注意的是 filter 过滤器代替了 query 查询,在本例中,我们无须使用全文搜索,只想找到 city 字段中包含 Barcelona 的所有文档,逻辑用过滤比用查询表达更清晰。过滤器返回的所有文档的评分 _score 的值为 1function_score 查询接受 queryfilter ,如果没有特别指定,则默认使用 match_all 查询。

函数 functions

functions 关键字保持着一个将要被使用的函数列表。可以为列表里的每个函数都指定一个 filter 过滤器,在这种情况下,函数只会被应用到那些与过滤器匹配的文档,例子中,我们为与过滤器匹配的文档指定权重值 weight1 (为与 pool 匹配的文档指定权重值为 2 )。

评分模式 score_mode

每个函数返回一个结果,所以需要一种将多个结果缩减到单个值的方式,然后才能将其与原始评分 _score 合并。评分模式 score_mode 参数正好扮演这样的角色,它接受以下值:

multiply:: 函数结果求积(默认)。

sum:: 函数结果求和。

avg:: 函数结果的平均值。

max:: 函数结果的最大值。

min:: 函数结果的最小值。

first:: 使用首个函数(可以有过滤器,也可能没有)的结果作为最终结果

在本例中,我们将每个过滤器匹配结果的权重 weight 求和,并将其作为最终评分结果,所以会使用 sum 评分模式。

不与任何过滤器匹配的文档会保有其原始评分, _score 值的为 1