如何使用Mongoose的$lookup多集合查询获取去重产品库存结果
MongoDB多集合关联计算库存问题解决方案
原代码存在的问题
- 过早执行
$unwind操作:$unwind "$sales"会直接过滤掉没有任何销售记录的产品,导致数据缺失;同时多次$unwind会生成销售记录和批次的笛卡尔积,导致后续求和时重复计算,结果偏差。 - 字段引用错误:聚合根是products集合,不存在
$products._id、$products.description这类字段,直接引用$_id、$description即可获取产品本身的属性。 $group阶段语法错误:同一个分组配置里写了两个_id字段,后定义的会覆盖前者,原本按产品属性分组的逻辑完全不生效。- 计算逻辑错误:先对单批次库存和单条销量做减法再求和的逻辑错误,正确逻辑应该是先统计该SKU所有批次的总入库量,再统计该SKU的总销量,最后用总入库量减总销量得到库存。
正确的聚合查询代码
db.products.aggregate([ // 可在此处添加产品过滤条件,无过滤需求可省略该$match阶段 { $lookup: { from: "batches", localField: "sku", foreignField: "sku", as: "batches" } }, { $lookup: { from: "sales", localField: "sku", foreignField: "sku", as: "sales" } }, { $project: { description: 1, stock: { $subtract: [ // 统计该SKU所有批次的总入库量,无批次则默认返回0 { $sum: "$batches.units" }, // 统计该SKU所有的总销量,无销量则默认返回0 { $sum: "$sales.quantityShipped" } ] } } } ])
步骤说明
- 先用两次
$lookup分别关联同一SKU的所有批次记录和销售记录,结果存在对应数组字段中,不需要$unwind拆分。 - 在
$project阶段直接用$sum对数组内的指定字段求和,直接得到总入库量和总销量,再做减法得到最终库存,避免了笛卡尔积导致的计算错误。 - 自动保留所有产品,无批次时库存为负销量,无销量时库存为总批次入库量,符合通用业务逻辑。
示例数据运行结果
针对你给出的示例数据,运行上述代码后返回结果如下,和预期输出格式完全匹配:
[ { "_id": "对应产品的_id值", "description": "A black Shoe", "stock": 30 } ]
内容的提问来源于stack exchange,提问作者samuel
相关产品推荐
相关产品推荐

