MongoDB 如何编写含$lookup、$group、$sum的聚合查询实现两集合关联求和
核心需求
关联MongoDB的collection1(商品主集合)、collection2(库存流水集合),保留collection1的全部原始记录,按照主从集合的外键关联关系,对collection2的quantity字段做分组求和,无匹配记录时求和值为0,最终输出指定结构的文档。
原尝试方案问题排查
此前采用“先对collection2全量分组求和,再执行$lookup关联collection1”的思路无法得到正确结果,通常是以下几个原因导致:
- 聚合顺序倒置:先对collection2全量聚合的流程中,后续$lookup关联只会返回能匹配到分组结果的主表文档,比如示例中Product4没有对应库存流水,会直接被过滤,不会出现在最终输出中。
- 关联条件缺失:如果$lookup阶段没有把主集合的
_id值透传到从集合的聚合管道中,会把从集合全量分组的结果直接挂载到每个主文档下,无法做到精准关联,最终求和值完全错位。 - 结构不匹配:直接将分组结果数组映射为
inventoryList字段时,会带上分组阶段生成的多余_id字段,和要求的输出结构不符。
正确实现写法
采用主集合驱动的聚合流程,既保证主集合全量数据不丢失,也能做到精准关联、实时求和,具体代码如下:
db.collection1.aggregate([ // 带管道的$lookup关联,实时匹配+求和 { $lookup: { from: "collection2", // 透传主集合的_id值,作为从集合的匹配条件 let: { currentProductId: "$_id" }, pipeline: [ // 仅匹配和当前商品关联的库存记录,避免全量扫描 { $match: { $expr: { $eq: ["$inventory", "$$currentProductId"] } } }, // 对匹配到的记录做quantity求和 { $group: { _id: "$inventory", quantity: { $sum: "$quantity" } } } ], as: "tempSumResult" } }, // 处理无匹配场景,生成要求的inventoryList结构 { $addFields: { inventoryList: { $cond: { if: { $eq: [{ $size: "$tempSumResult" }, 0] }, then: [{ quantity: 0 }], else: "$tempSumResult" } } } }, // 字段重命名、清理临时字段 { $project: { _id1: "$_id", name: 1, units: 1, inventoryList: 1, _id: 0 } } ])
实现效果说明
执行上述聚合后,返回的结果完全符合要求:
- Product1关联3条库存流水,求和
20+10+50=80 - Product2关联2条库存流水,求和
4+45=49 - Product3关联1条库存流水,求和
49 - Product4无匹配库存流水,求和值为
0
内容的提问来源于stack exchange,提问作者3bu1
相关产品推荐
相关产品推荐

