如何调整MongoDB聚合查询将结果转换为[疫苗名称,库存数量]嵌套数组格式
如何将MongoDB聚合结果转换为嵌套数组格式
当然有可行的实现方式!你可以通过两种思路达成目标——要么在MongoDB聚合管道内直接生成你想要的嵌套数组格式,要么在Node.js端对聚合返回的结果做简单转换。下面给你详细拆解这两种方案:
方案一:在聚合管道内完成转换
这种方式适合数据量较大的场景,能减少从数据库传输到客户端的数据量。你只需要在现有聚合步骤的最后,添加几个步骤来重组数据结构:
通用版(支持多疫苗结果)
如果后续可能有多个疫苗的统计结果,推荐用这个版本:
const vaccination = await Schedule.aggregate([ { $match: { status: ScheduleStatus.Published } }, { "$unwind": { "path": "$vaccines", "preserveNullAndEmptyArrays": true } }, { "$group": { "_id": "$vaccines.vaccine", "count": { "$sum": "$vaccines.stok" } } }, { $lookup: { from: 'vaccines', localField: '_id', foreignField: '_id', as: 'vaccine' } }, // 提取疫苗名称并隐藏_id { $project: { vaccineName: { "$arrayElemAt": ["$vaccine.name", 0] }, count: 1, _id: 0 } }, // 将每个文档转为 [疫苗名, 数量] 的数组 { $project: { item: ["$vaccineName", "$count"] } }, // 把所有数组合并成一个大数组 { $group: { _id: null, result: { $push: "$item" } } }, // 只保留最终结果数组 { $project: { _id: 0, result: 1 } } ]);
执行后返回的结果是:
[ { "result": [["Sinovac", 20]] } ]
你只需要取vaccination[0].result就能拿到目标格式的嵌套数组。
简化版(仅单个疫苗结果)
如果确定只会有一个疫苗的统计结果,可以简化最后几步,直接生成目标格式:
const vaccination = await Schedule.aggregate([ // 保留原有的聚合步骤 { $match: { status: ScheduleStatus.Published } }, { "$unwind": { "path": "$vaccines", "preserveNullAndEmptyArrays": true } }, { "$group": { "_id": "$vaccines.vaccine", "count": { "$sum": "$vaccines.stok" } } }, { $lookup: { from: 'vaccines', localField: '_id', foreignField: '_id', as: 'vaccine' } }, // 直接生成 [疫苗名, 数量] 的数组结构 { $project: { _id: 0, item: [{ "$arrayElemAt": ["$vaccine.name", 0] }, "$count"] } }, // 将数组设为文档根节点 { $replaceRoot: { newRoot: "$item" } } ]);
这个版本执行后,返回的结果就是你想要的[["Sinovac", 20]]。
方案二:在Node.js端转换结果
如果数据量不大,这种方式代码更简洁易维护,不需要修改原有的聚合管道:
// 保留原有的聚合查询代码 const vaccination = await Schedule.aggregate([ { $match: { status: ScheduleStatus.Published } }, { "$unwind": { "path": "$vaccines", "preserveNullAndEmptyArrays": true } }, { "$group": { "_id": "$vaccines.vaccine", "count": { "$sum": "$vaccines.stok" } } }, { $lookup: { from: 'vaccines', localField: '_id', foreignField: '_id', as: 'vaccine' } }, { $project: { "count": 1, "vaccine": { "$arrayElemAt": ["$vaccine.name", 0] } } } ]); // 用Array.map快速转换为目标格式 const formattedResult = vaccination.map(item => [item.vaccine, item.count]);
转换后formattedResult的值就是[["Sinovac", 20]]。
两种方案各有优劣,你可以根据自己的业务场景选择~
内容的提问来源于stack exchange,提问作者Evan Samuel
相关产品推荐
相关产品推荐

