Elasticsearch 8.7.1:限制terms聚合中每个itemId的响应条数
问题描述
使用Elasticsearch 8.7.1版本查询时,希望限制每个itemDetails.itemId对应的返回记录数(例如设置size=2时,每个itemId返回2条记录),但当前查询返回了所有distinct cId的结果,不符合预期。
示例Elasticsearch文档
{ "itemDetails": { "itemId": "3076", "usecase": "habc", "usecaseId": "xyz" }, "metaData": { "cId": "96ff54507c2d018e5c767785c705a5b2", "date1": "2023-09-29T12:29:54", "date2": "2023-09-29T12:30:09" }, // 其他属性... }
当前输入查询语句
POST /index/_search?typed_keys=true { "size": 0, "query": { "bool": { "must": [ { "terms": { "itemDetails.itemId": [ "3076", "1111", "2222" ] } }, { "terms": { "itemDetails.usecase": [ "habc" ] } }, { "range": { "metaData.date1": { "lte": "2023-09-30T19:55:54.611Z", "gte": "2023-09-27T19:55:54.611Z" } } } ] } }, "aggs": { "distinct_cIds": { "terms": { "field": "metaData.cId", "order": { "max_date1": "desc" } }, "aggs": { "max_date1": { "max": { "field": "metaData.date1" } }, "top_doc": { "top_hits": { "size": 1, "sort": [ {"metaData.date1": "desc"}, {"metaData.date2": "desc"} ], "_source": { "includes": [ "itemDetails.itemId", "itemDetails.usecase", "metaData.cId", "metaData.date1" ] } } } } } } }
当前返回响应问题
返回结果会遍历所有distinct cId并输出对应记录,无法实现按itemId限制返回数量的需求,示例响应片段:
"buckets": [ { "key": "f8d79b2856e894c9e88852f65120e9e3", "doc_count": 1, "sterms#distinct_itemId": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "3076", "doc_count": 1, "top_hits#top_doc": { "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": null, "hits": [{}] } } } ] }, "max#max_date1": { "value": 1697385179000, "value_as_string": "2023-10-15T15:52:59.000Z" } }, { "key": "153c067041341dc4d2052313d3f0891f", "doc_count": 1, "sterms#distinct_itemId": { "doc_count_error_upper_bound": 0, "sum_other_doc_count": 0, "buckets": [ { "key": "3076", "doc_count": 1, "top_hits#top_doc": { "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": null, "hits": [{}] } } } ] }, "max#max_date1": { "value": 1697303179000, "value_as_string": "2023-10-14T17:06:19.000Z" } } // 更多cId记录... ]
解决方案
调整聚合层级,先按itemDetails.itemId分桶,再在每个itemId桶内通过top_hits聚合获取指定数量的记录(比如size=2),即可实现每个itemId限制返回条数的需求:
POST /index/_search?typed_keys=true { "size": 0, "query": { "bool": { "must": [ { "terms": { "itemDetails.itemId": ["3076", "1111", "2222"] } }, { "terms": { "itemDetails.usecase": ["habc"] } }, { "range": { "metaData.date1": { "lte": "2023-09-30T19:55:54.611Z", "gte": "2023-09-27T19:55:54.611Z" } } } ] } }, "aggs": { "per_itemId": { "terms": { "field": "itemDetails.itemId", "include": ["3076", "1111", "2222"], // 可选,与query过滤保持一致 "size": 3 // 对应指定的3个itemId数量 }, "aggs": { "top_records": { "top_hits": { "size": 2, // 每个itemId返回2条记录 "sort": [ {"metaData.date1": "desc"}, {"metaData.date2": "desc"} ], "_source": { "includes": [ "itemDetails.itemId", "itemDetails.usecase", "metaData.cId", "metaData.date1" ] } } } } } } }
说明
- 外层聚合
per_itemId按itemDetails.itemId分桶,确保每个itemId单独统计; - 内层
top_records聚合通过size参数控制每个itemId返回的记录数,同时保留原有的排序规则; include和size参数可选,因为query已经过滤了目标itemId,加上后能更精准地限制聚合范围。
内容的提问来源于Stack Exchange,提问作者Amulya M
相关产品推荐
相关产品推荐

