在Elasticsearch中使用function_score时,过滤器是在function_score对象内部还是外部



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

我们的想法是…使用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对此进行了优化而没有必要?

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

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

最新更新