如何构建Elasticsearch查询获取仅含Open状态的指定id分组
Elasticsearch按id分组检索:仅保留全组满足状态为'Open'且标签含"X1"的分组
我需要构建一个Elasticsearch查询,基于id字段对文档分组,要求每个分组内的所有文档都必须满足状态为Open且标签包含子串"X1"。
数据示例
id, status, label, date 1, CLOSED, X1, 07/02/2024 1, OPEN, X1, 07/02/2024 2, OPEN, X1, 07/02/2024 2, OPEN, X1, 05/02/2024 3, OPEN, X1, 07/02/2024 1, OPEN, X2, 07/02/2024
期望结果
只返回id=2的分组(该分组所有文档均符合条件),示例返回:
2, OPEN, X1, 07/02/2024
实现方案
通过聚合+过滤+桶选择器的组合实现,核心逻辑是先分组,再排除存在不符合条件文档的分组,最后提取目标文档:
- 按
id字段分组; - 统计每个分组内不符合条件的文档数量;
- 仅保留无不符合文档的分组;
- 获取分组内的目标文档(如最新一条)。
完整查询DSL
{ "size": 0, "aggs": { "group_by_id": { "terms": { "field": "id", "size": 1000 }, "aggs": { "invalid_docs": { "filters": { "filters": { "not_open": { "bool": { "must_not": { "term": { "status.keyword": "OPEN" } } } }, "not_x1": { "bool": { "must_not": { "wildcard": { "label.keyword": "*X1*" } } } } } }, "aggs": { "total_invalid": { "sum_bucket": { "buckets_path": "_count" } } } }, "valid_bucket_filter": { "bucket_selector": { "buckets_path": { "invalidCount": "invalid_docs>total_invalid" }, "script": "params.invalidCount == 0" } }, "latest_doc": { "top_hits": { "size": 1, "sort": [ { "date": { "order": "desc" } } ] } } } } } }
关键说明
terms聚合:按id分组,若id为文本类型,需替换为id.keyword(根据实际映射调整);invalid_docs聚合:统计分组内「状态非OPEN」或「标签不含X1」的文档总数;bucket_selector:仅保留invalidCount=0的分组,即全组文档均符合要求;top_hits:获取分组内的文档,此处配置为取最新一条(按date降序),可根据需求调整size和排序规则。
结果解析
查询返回的aggregations.group_by_id.buckets中,每个符合条件的分组会包含latest_doc.hits.hits,里面就是目标文档。若需返回分组内所有符合条件的文档,可将top_hits的size设为足够大的值。
内容的提问来源于stack exchange,提问作者skizofre3e
相关产品推荐
相关产品推荐

