MongoDB Aggregation $sum嵌套分组实现国家区域层级统计
MongoDB按国家-区域分层统计事件数解决方案
现有数据与需求
events集合存储的样例数据如下:
[ { country: "USA", Region: "CA", City: "Los Angeles" }, { country: "USA", Region: "NY", City: "New York" }, { country: "USA", Region: "NY", City: "White Plains" }, { country: "France", Region: "Ile-de-France", City: "Paris" }, { country: "France", Region: "Bretagne", City: "Brest" }, { country: "Germany", Region: "", City: "Berlin" } ]
需要按country、Region两个维度分层统计事件计数,期望输出结构为国家维度总计数+下属区域维度计数的嵌套格式,空Region不需要展示在子项列表中。
原有聚合语句的错误点
你之前写的聚合管道存在两个核心问题:
- 第一个
$group阶段仅按country单维度分组,输出结果已经丢失了所有Region维度的明细信息,后续阶段无法再基于Region做统计 - 第二个
$group阶段字段引用逻辑错误:第一阶段输出的_id直接是国家字符串值(例如"USA"),不存在$_id.country这个嵌套属性,因此最终分组键会返回null;同时$push是普通表达式操作符,内部不能直接嵌套$sum这类聚合累加器,累加器只能作为$group阶段的顶层配置项使用。
正确聚合实现
分层统计需要先从最细粒度的(国家+区域)组合开始分组计数,再向上聚合到国家维度,完整代码如下:
events.aggregate([ // 第一步:按「国家+区域」最细粒度分组,统计每个组合的事件数 { $group: { _id: { country: "$country", Region: "$Region" }, regionCount: { $sum: 1 } } }, // 第二步:按国家维度聚合,计算国家总计数,同时收集有效子区域的统计结果 { $group: { _id: "$_id.country", count: { $sum: "$regionCount" }, children: { $push: { // 空Region不推入子项列表,匹配德国的空Region场景 $cond: [ { $ne: ["$_id.Region", ""] }, { Region: "$_id.Region", count: "$regionCount" }, "$$REMOVE" ] } } } }, // 第三步:调整输出字段结构,匹配期望格式 { $project: { _id: 0, country: "$_id", count: 1, children: 1 } } ])
执行后输出结果和期望格式完全一致:
- USA总计数3,下属NY计数2、CA计数1
- France总计数2,下属两个区域各计数1
- Germany总计数1,空Region被过滤,children为空数组
如果业务中还存在Region为null或undefined的场景,只需要修改$cond的判断条件,把这类值也纳入过滤范围即可。
内容的提问来源于stack exchange,提问作者Caldera500
相关产品推荐
相关产品推荐

