如何在MongoDB的$group聚合中使用$subtract并关联查询产品客户数据
MongoDB purchase集合聚合查询实现方案
完整聚合语句
db.purchase.aggregate([ // 可选:先过滤已售出的单据,减少后续计算量 { $match: { isSold: true, status: "Sold" } }, // 分组聚合计算总利润 { $group: { _id: { product: "$product", customer: "$customer", unitprice: "$unitprice", unitcost: "$unitcost" }, // 直接在group中使用$subtract计算单条利润再累加,无需中间字段 profit: { $sum: { $subtract: ["$unitprice", "$unitcost"] } } } }, // 关联product集合获取产品详情 { $lookup: { from: "product", localField: "_id.product", foreignField: "_id", as: "productDetails" } }, { $unwind: "$productDetails" }, // 关联customer集合获取客户详情 { $lookup: { from: "customer", localField: "_id.customer", foreignField: "_id", as: "customerDetails" } }, { $unwind: "$customerDetails" }, // 调整输出结构,匹配要求的格式 { $project: { _id: 0, productDetails: { _id: 1, title: 1 }, profit: 1, unitprice: "$_id.unitprice", unitcost: "$_id.unitcost", customerDetails: { _id: 1, title: 1 } } } ])
关键逻辑说明
$subtract算子在$group阶段的使用
$subtract是MongoDB的算术聚合算子,接收两个数值参数,返回「第一个参数 - 第二个参数」的差值。在本次需求中,我们直接将其嵌入$group的$sum累加器中:
- 每一条分组内的单据都会先执行
$subtract: ["$unitprice", "$unitcost"]计算单条商品的利润 - 再通过$sum将所有单条利润累加,得到该分组下的总利润,完全不需要额外新增中间字段存储单条利润,效率更高
其他阶段说明
- $match:可选阶段,提前过滤未售出的单据,减少后续计算的数据量,可根据业务需求决定是否保留
- 复合分组键说明:因为输出结构中包含customerDetails,所以我们使用了product+customer+单价成本的复合分组键,如果你的业务场景中同一产品的所有售卖记录都对应同一个客户,可自行调整分组键仅保留product字段
- $lookup + $unwind:分别关联产品和客户集合,因为单个purchase记录的product和customer都是单值关联,$unwind可以将lookup返回的单元素数组转为对象,符合输出结构要求
- $project:最终调整输出字段,过滤不需要的属性,将分组键中的unitprice、unitcost提取到根层级,匹配要求的输出格式
内容的提问来源于stack exchange,提问作者SAURABH RATHOD
相关产品推荐
相关产品推荐

