在Elasticsearch中使用function_score时,是否在function_score对象内部或外部使用过滤器是否重要?

时间:2018-11-19 12:05:40

标签: performance elasticsearch

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

想法是...使用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为此而进行了优化,所以不必要吗?

1 个答案:

答案 0 :(得分:1)

您可以将过滤器保留在function_score查询之外。这样的想法是,如果您有多个function_score查询,则过滤仅执行一次,然后所有功能分数都将在过滤后的数据集上运行。

此外,如果您除了function_score查询之外还具有汇总,则一定要让过滤器位于外部,以便也可以在精简文档集中计算汇总。过滤器都是为了减少需要运行昂贵计算的文档集。