如何过滤elasticsearch全局聚合?

adr*_*ois 11 aggregation elasticsearch

我想要实现的目标:我希望我的"年龄"聚合不被查询过滤器过滤,我希望能够对其应用过滤器.

所以,如果我从这个查询开始:

{
    "query":{
        "filtered":{
            "filter":{ "terms":{ "family_name":"Brown" } } //filter_1
        }
    },
    "aggs":{
        "young_age":{
            "filter":{
                "range":{ "lt":40, "gt":18 } //filter_2
            },
            "aggs":{
                "age":{
                    "terms":{
                        "field":"age"
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我的聚合"young_age"将由filter_1和filter_2过滤.我不希望我的聚合被filter_1过滤.

当我查看文档时,我认为全局聚合将解决我的问题,并且我编写了该查询:

{
    "query":{
        "filtered":{
            "filter":{ "terms":{ "family_name":"Brown" } } //filter_1
        }
    },
    "aggs":{
        "young_age":{
            "global":{}, //<----------- add global
            "filter":{
                "range":{ "lt":40, "gt":18 } //filter_2
            },
            "aggs":{
                "age":{
                    "terms":{
                        "field":"age"
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是弹性搜索会抱怨我的filter_2:

msgstr"""在[global]和[filter]中找到了两个聚合类型定义[age]"""

当然,如果我删除filter_2:

{
    "query":{
        "filtered":{
            "filter":{
                "terms":{
                    "family_name":"Brown"
                }
            }
        }
    },
    "aggs":{
        "young_age":{
            "global":{},
            "aggs":{
                "age":{
                    "terms":{
                        "field":"age"
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我的聚合将不会被filter_1过滤(如预期的那样).

那么我想如何将filter_2应用于我的全局聚合?或者我该如何实现呢?我记得用facet滤镜写了类似的东西......

mol*_*are 8

在我看来,这是post_filter的典型用例。正如文档所说:

post_filter 应用于搜索请求最后的搜索命中,在聚合已经计算之后

您的查询将如下所示:

{
    "post_filter":{
       "terms":{
            "family_name":"Brown" //filter_1
        }
    },
   "aggs":{
        "young_age":{
            "filter":{
                "range":{ "lt":40, "gt":18 } //filter_2
            },
            "aggs":{
                "age":{
                    "terms":{
                        "field":"age"
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,搜索命中是索引中的所有文档。然后计算聚合(在 filter_1 之前)。之后post_filter与 filter_1 将被执行。

编辑:正如你在你的推荐中所说,你有很多聚合,只有一个不受filter_1我使用全局聚合修复你的查询的影响

{
  "query": {
    "filtered": {
      "filter": {
        "term": {
          "family_name": "Brown"
        }
      }
    }
  },
  "aggs": {
    "young_age": {
      "global": {},
      "aggs": {
        "filter2": {
          "filter": {
            "range": {
              "lt": 40,
              "gt": 18
            }
          },
          "aggs": {
            "age": {
              "terms": {
                "field": "age"
              }
            }
          }
        }
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 这可行,但实际上我有很多聚合,只有其中一个不应该被 filter_1 过滤。因此,对于您的解决方案,这意味着我必须为那些聚合复制 post_filter ,我觉得这有点烦人(而且从性能的角度来看可能也不是那么好?) (2认同)