Elasticsearch 5.6聚合与过滤:按类别获取最新文档并后续过滤
嘿,针对你在Elasticsearch 5.6里按name分组获取每个类别下最新文档的需求,我给你整理了两种实用的方案,都是5.6版本完全支持的:
方案1:使用
top_hits聚合(推荐) 这是Elasticsearch中按分组取最新/最旧文档的标准做法,逻辑清晰且性能稳定。你可以先通过terms聚合按name完成分组,再在每个分组内用top_hits获取按时间排序后的第一条文档(也就是每个类别下的最新记录)。
完整查询DSL如下:
{ "size": 0, "aggs": { "group_by_service_name": { "terms": { "field": "name.keyword", "size": 1000 // 这里设置你需要的类别数量上限,默认是10,按需调整 }, "aggs": { "latest_status_record": { "top_hits": { "size": 1, "sort": [ { "@timestamp": { "order": "desc" } } ], "_source": { "includes": ["name", "@timestamp", "statusInfo"] // 只返回你关心的字段,提升查询效率 } } } } } } }
关键细节说明:
"size": 0:我们只需要聚合结果,不需要返回原始匹配文档,设为0能节省资源terms聚合用name.keyword:如果你的name字段是text类型,必须用它的keyword子字段做精确分组(否则text会被分词,分组结果会不符合预期)top_hits的size:1:确保每个分组只返回排序后的第一条数据- 按
@timestamp倒序排序:保证拿到的是每个name下最新的文档 _source.includes:指定返回字段,避免无用数据拖慢查询速度
方案2:使用
collapse折叠功能 如果你希望返回的结构更接近普通搜索结果(而非嵌套在聚合里),可以用collapse按name折叠,再结合inner_hits获取最新文档。5.6版本已经支持这个特性:
{ "query": { "match_all": {} }, "collapse": { "field": "name.keyword" }, "sort": [ { "@timestamp": { "order": "desc" } } ], "inner_hits": { "name": "latest_status", "size": 1, "sort": [ { "@timestamp": { "order": "desc" } } ], "_source": { "includes": ["name", "@timestamp", "statusInfo"] } }, "size": 1000 }
额外注意事项:
- 确保你的
@timestamp字段映射是date类型,如果之前是字符串格式,建议先修改映射(临时用脚本转换的方式会影响性能,不推荐) - 如果
name字段本身就是keyword类型(没有text子字段),直接用"field": "name"即可 - 如果类别数量较多,记得调整
terms或size参数的数值,避免默认值截断结果
内容的提问来源于stack exchange,提问作者Matthieu Borgraeve
相关产品推荐
相关产品推荐

