如何用Mongoose实现硬币数据按国家、系列多级聚合?
MongoDB聚合实现「国家-系列-硬币」层级结构输出
问题描述
在MongoDB中存储了大量硬币数据,后端基于Mongoose+Express开发,需要实现接口将硬币数据按「国家-系列-硬币」的层级结构聚合输出,方便前端调用。现有聚合代码无法将硬币正确归入对应系列。
输入数据示例
[ { "_id": "643d5bf4637daa055466d8f0", "country": "AND", "denomination": 0.01, "series": 1 }, { "_id": "643d5bf4637daa055466d8f1", "country": "AND", "denomination": 0.02, "series": 1 }, { "_id": "643d5bf4637daa055466d8f2", "country": "USA", "denomination": 1, "series": 2 } ]
期望输出格式
[ { "country": "AND", "series": [ { "series": 1, "coins": [ { "_id": "643d5bf4637daa055466d8f0", "country": "AND", "denomination": 0.01, "series": 1 }, { "_id": "643d5bf4637daa055466d8f1", "country": "AND", "denomination": 0.02, "series": 1 } ] } ] }, { "country": "USA", "series": [ { "series": 2, "coins": [ { "_id": "643d5bf4637daa055466d8f2", "country": "USA", "denomination": 1, "series": 2 } ] } ] } ]
现有代码(存在问题)
const coins = await Coin.aggregate([ { $group: { _id: '$country', series: { $addToSet: { series: '$series', coins: [] } }, }, }, { $addFields: { country: '$_id' }, }, { $project: { _id: 0, }, }, { $sort: { country: 1 }, }, ]);
完整聚合解决方案
要实现目标层级结构,需要分两次分组:先按「国家+系列」聚合硬币数据,再按「国家」聚合系列信息。完整代码如下:
const coins = await Coin.aggregate([ // 第一步:按国家+系列分组,收集同系列下的所有硬币 { $group: { _id: { country: '$country', series: '$series' }, coins: { $push: '$$ROOT' } // 将当前完整硬币文档加入coins数组 } }, // 第二步:按国家分组,整合同一国家的所有系列数据 { $group: { _id: '$_id.country', series: { $push: { series: '$_id.series', coins: '$coins' } } } }, // 将国家名称从_id转移到country字段 { $addFields: { country: '$_id' } }, // 移除默认_id字段,匹配期望输出结构 { $project: { _id: 0 } }, // 按国家名称升序排序 { $sort: { country: 1 } } ]);
代码说明
第一次$group:
- 用
{country: '$country', series: '$series'}作为分组ID,确保同一国家同系列的硬币被归为一组 - 通过
$push: '$$ROOT'保留硬币的完整文档,存入coins数组
- 用
第二次$group:
- 按国家维度重新分组,将第一次分组得到的系列对象(包含系列编号和对应硬币数组)整合到
series数组中
- 按国家维度重新分组,将第一次分组得到的系列对象(包含系列编号和对应硬币数组)整合到
后续阶段:
$addFields将国家名称从_id字段转移到country字段,符合输出格式$project移除默认生成的_id字段$sort保证输出结果按国家名称有序排列
内容的提问来源于stack exchange,提问作者Klak031
相关产品推荐
相关产品推荐

