ElasticSearch聚合查询实现按国家分组返回Top2城市
核心逻辑偏差
原有查询聚合嵌套顺序倒置:当前逻辑为先聚合城市、再关联所属国家,无法实现「按国家维度分组、每个分组取Top2城市」的效果,需将聚合层级从外到内调整为「国家分组→组内取Top2城市」。
调整方案
Elasticsearch的terms聚合默认按匹配文档数(即内容出现频次,对应常规热度统计逻辑)降序排序,天然符合「优先返回高热度国家、每个国家优先返回高热度城市」的要求,调整规则如下:
- 最外层第一层聚合:按
user.country_id做terms聚合,size参数设置为需要返回的国家总数量 - 第二层子聚合(嵌套在国家聚合内部):按
user.city_id做terms聚合,size固定设为2,即可拿到每个国家下热度前2的城市 - 如果需要关联返回用户名等附属字段,在城市聚合下继续嵌套对应子聚合即可
调整后的完整查询语句
{ "size": 0, "query": { "bool": { "must": [ { "term": { "user.category": 1 } } ] } }, "aggs": { "group_by_country": { "terms": { "field": "user.country_id", "size": 999 }, "aggs": { "top2_cities": { "terms": { "field": "user.city_id", "size": 2 }, "aggs": { "user_name_info": { "terms": { "field": "user.name", "size": 1 } } } } } } } }
特殊场景适配
如果使用的「热度」是单独存储的数值字段(比如存在user.hot_score字段记录单条数据的热度值),只需要给两层terms聚合增加对应排序规则即可,示例调整片段:
"aggs": { "group_by_country": { "terms": { "field": "user.country_id", "size": 999, "order": { "country_hot_sum": "desc" } }, "aggs": { "country_hot_sum": { "sum": { "field": "user.hot_score" } }, "top2_cities": { "terms": { "field": "user.city_id", "size": 2, "order": { "city_hot_sum": "desc" } }, "aggs": { "city_hot_sum": { "sum": { "field": "user.hot_score" } }, "user_name_info": { "terms": { "field": "user.name", "size": 1 } } } } } } }
内容的提问来源于stack exchange,提问作者JuanCruz
相关产品推荐
相关产品推荐

