如何实现MongoDB文档的投影与分对象聚合查询?
正确的MongoDB聚合查询实现方案
原代码问题分析
- 连续使用两次
$facet导致过滤后的数据集被重复处理,性能损耗明显 - 第二个
$facet的$project阶段引用了不存在的_count字段,逻辑错误 - 聚合计数逻辑缺失,无法生成符合预期的
aggregates结构
正确聚合查询实现
const res = await BusDayWiseBreakDown.aggregate([ { $match: { varId, status } }, { $facet: { // 生成目标结果数组,只保留指定字段 result: [ { $project: { _id: 1, varId: 1, status: 1 } } ], // 计算聚合统计值 aggregates: [ { $group: { _id: null, _count: { $sum: 1 }, collection: { $sum: "$collection" }, cash: { $sum: "$cash" }, upi: { $sum: "$upi" }, driverSalary: { $sum: "$driverSalary" } } }, { $project: { _id: 0 // 移除分组生成的冗余_id字段 } } ] } }, { // 将聚合结果数组转为单个对象($group后返回的是单元素数组) $addFields: { aggregates: { $arrayElemAt: ["$aggregates", 0] } } } ]).session(mongoSession); return res[0]; // 聚合返回数组,取第一个元素即为目标结构
代码逻辑说明
- $match阶段:先过滤出符合
varId和status条件的文档,减少后续处理的数据量,从根源提升性能 - $facet阶段:并行执行两个处理分支,避免重复遍历数据集:
result分支:通过$project直接保留需要的三个字段,生成目标结果数组aggregates分支:$group:以null为分组键,一次性计算文档计数_count和各数值字段的总和$project:移除分组自动生成的_id字段,整理聚合结果格式
- $addFields阶段:将
aggregates的单元素数组转为单个对象,匹配预期输出结构 - 最后返回聚合结果数组的第一个元素,得到符合需求的完整结构
内容的提问来源于stack exchange,提问作者Roomi
相关产品推荐
相关产品推荐

