MongoDB 4.4聚合:按州分组去重嵌套城市值问题
MongoDB v4.4 按州分组生成去重城市列表解决方案
数据结构与需求
集合文档结构
每个文档包含addresses数组,示例:
"addresses": [ { "state": "New York", "city": "New York" }, { "state": "New York", "city": "Buffalo" }, { "state": "Massachusetts", "city": "Boston" }, ... ]
预期输出
跨所有文档生成按state分组的去重city列表:
[ { "state": "New York", "cities": [ "New York", "Buffalo" ] }, { "state": "Massachusetts", "cities": [ "Boston" ] }, ... ]
现有查询问题分析
第一个查询仅返回部分州
执行以下聚合仅得到20个州(实际集合包含50个州):
db.locations.aggregate([ { $unwind: {path: "$addresses" }}, { $group: { _id: "$addresses.state", cities: { $addToSet: '$addresses.city' } } } ])
问题原因:查询逻辑本身正确,大概率是客户端工具默认分页(比如Mongo Shell默认只显示前20条),输入it命令即可加载剩余结果;也可能是你无意中添加了未提及的$match过滤条件。
第二个查询未按州分组
返回的州和城市存入两个无序数组,核心问题是$group的_id设置错误(比如设为null或固定值,导致所有数据聚合到同一组)。
正确聚合管道
以下代码可实现需求,完全匹配预期输出:
db.locations.aggregate([ // 展开所有文档中的addresses数组,拆分每个地址为独立文档 { $unwind: "$addresses" }, // 按州分组,用$addToSet自动去重收集城市 { $group: { _id: "$addresses.state", cities: { $addToSet: "$addresses.city" } } }, // 重命名字段,让输出结构与预期一致 { $project: { _id: 0, state: "$_id", cities: 1 } }, // 可选:按州名排序,结果更规整 { $sort: { state: 1 } } ])
关键步骤说明
$unwind:确保每个地址条目都被单独处理,不会遗漏跨文档的州/城市组合$group:以addresses.state为分组键,$addToSet自动过滤重复城市$project:将分组用的_id重命名为state,移除多余的_id字段- 如果结果显示不全,在Mongo Shell中执行
it命令加载下一页,直到无更多结果
内容的提问来源于stack exchange,提问作者Nate Scholnick
相关产品推荐
相关产品推荐

