【问题标题】:When using function_score in Elasticsearch, does it matter if filters are inside or out the function_score object?在 Elasticsearch 中使用 function_score 时,过滤器是在 function_score 对象内部还是外部是否重要?
【发布时间】:2018-11-19 20:09:22
【问题描述】:

我正在查看一些旧代码,以及是否有必要对其进行重构以提高性能。

我们的想法是......使用 function_score,您正在将一个函数应用于您想要返回的所有文档,所以,如果您只能在您需要的文档上运行这些函数,那就更好了。

目前这样做的方式有点像这样(我已经简化了查询以在此处讨论):

{
  "query": {
    "bool": {
      "must": {
        "function_score": {
          "query": {
            "match_all": {}
          },
          "functions": [
            {
              "gauss": {
                "updated_at": {
                  "origin": "now",
                  "scale": "7d",
                  "offset": "2d",
                  "decay": 0.5
                }
              }
            }
          ]
        }
      },
      "filter": [
        {
          "bool": {
            "must": [
              {
                "term": {
                  "indexed": true
                }
              }
            ],
            "must_not": [
              {
                "terms": {
                  "sale_stage": [
                    "on_hold",
                    "withdrawn",
                    "off_market"
                  ]
                }
              }
            ],
          }
        }
      ]
    }
  },
  "sort": [
    "_score",
    "_uid"
  ],
}

查询的内容并不重要。重要的是功能得分之外还有过滤器。

查询运行良好,并返回正确的数据。但是,我是否认为分数函数正在索引中的所有文档上运行然后被过滤,或者 ES 是否足够聪明地在这里优化,因为它知道我想要一组过滤的数据?

换句话说,我可以让查询保持原样吗,还是应该变成这样:

{
  "query": {
    "bool": {
      "must": {
        "function_score": {
          "query": {
            "bool": {
              "must": {
                "match_all": {}
              },
              "filter": [
                {
                  "bool": {
                    "must": [
                      {
                        "term": {
                          "indexed": true
                        }
                      }
                    ],
                    "must_not": [
                      {
                        "terms": {
                          "sale_stage": [
                            "on_hold",
                            "withdrawn",
                            "off_market"
                          ]
                        }
                      }
                    ]
                  }
                }
              ]
            }
          },
          "functions": [
            {
              "gauss": {
                "updated_at": {
                  "origin": "now",
                  "scale": "7d",
                  "offset": "2d",
                  "decay": 0.5
                }
              }
            }
          ]
        }
      }
    }
  },
  "sort": [
    "_score",
    "_uid"
  ],
}

在第二个示例中,查询的意图是相同的,但我已将所有过滤移至评分函数中。原因是,如果我有一个非常昂贵的功能(比如地理间距的东西),我不想在每个文档上运行它。

我需要做这个小的重构还是因为 ES 对此进行了优化而没有必要?

【问题讨论】:

    标签: performance elasticsearch


    【解决方案1】:

    您可以将过滤器留在function_score 查询之外。其想法是,如果您有多个 function_score 查询,则只进行一次过滤,然后在过滤后的数据集上运行所有函数分数。

    此外,如果您除了 function_score 查询之外还有聚合,那么一定要把过滤器放在外面,这样聚合也可以在缩减的文档集上计算。过滤器旨在减少需要运行昂贵计算的文档集。

    【讨论】:

    • 是的,谢谢。当你回答时我想将其标记为答案但不能然后忘记回到我们的??
    • 酷,很高兴它有帮助!
    猜你喜欢
    • 1970-01-01
    • 2016-11-24
    • 1970-01-01
    • 2016-02-01
    • 2018-03-11
    • 2018-10-07
    • 2017-02-03
    • 1970-01-01
    • 2020-03-08
    相关资源
    最近更新 更多