MongoDB跨集合计算总销售额:Outlet-A及2018年营收查询需求
没问题,这两个跨集合计算营收的需求,用MongoDB的聚合框架结合$lookup就能轻松搞定!先假设你的集合结构大概是这样(如果实际字段有出入,调整匹配条件即可):
sales集合字段示例:_id,productId(关联products的_id),outlet(门店名称),saleDate(销售日期,Date类型),quantity(销售数量)products集合字段示例:_id,price(产品单价)
1. 计算Outlet-A产生的总营收
这个查询会先筛选出门店为Outlet-A的销售记录,关联对应产品的价格,计算每条记录的营收(数量×单价)后求和:
db.sales.aggregate([ // 第一步:筛选Outlet-A的销售记录 { $match: { outlet: "Outlet-A" } }, // 第二步:关联products集合,匹配产品ID { $lookup: { from: "products", localField: "productId", foreignField: "_id", as: "productInfo" } }, // 第三步:展开关联的产品信息数组($lookup默认返回数组) { $unwind: { path: "$productInfo", preserveNullAndEmptyArrays: true } }, // 第四步:计算单条销售的营收,兼容无匹配产品的情况(设为0) { $addFields: { revenue: { $multiply: [ "$quantity", { $ifNull: ["$productInfo.price", 0] } ] } } }, // 第五步:求和所有营收 { $group: { _id: null, totalRevenueOutletA: { $sum: "$revenue" } } }, // 可选:重命名字段让输出更直观 { $project: { _id: 0, "Outlet-A总营收": "$totalRevenueOutletA" } } ])
2. 计算2018年产生的总营收
这个查询先筛选2018年的销售记录,同样关联产品价格后求和:
db.sales.aggregate([ // 第一步:筛选2018年的销售记录(针对Date类型的saleDate) { $match: { saleDate: { $gte: ISODate("2018-01-01T00:00:00Z"), $lt: ISODate("2019-01-01T00:00:00Z") } } }, // 第二步:关联products集合 { $lookup: { from: "products", localField: "productId", foreignField: "_id", as: "productInfo" } }, // 第三步:展开关联数组 { $unwind: { path: "$productInfo", preserveNullAndEmptyArrays: true } }, // 第四步:计算单条营收 { $addFields: { revenue: { $multiply: [ "$quantity", { $ifNull: ["$productInfo.price", 0] } ] } } }, // 第五步:求和所有营收 { $group: { _id: null, totalRevenue2018: { $sum: "$revenue" } } }, // 可选:重命名字段 { $project: { _id: 0, "2018年总营收": "$totalRevenue2018" } } ])
优化补充:一次性计算两个结果
如果想同时得到两个总营收,用$facet可以只做一次跨集合关联,效率更高:
db.sales.aggregate([ { $lookup: { from: "products", localField: "productId", foreignField: "_id", as: "productInfo" } }, { $unwind: { path: "$productInfo", preserveNullAndEmptyArrays: true } }, { $addFields: { revenue: { $multiply: [ "$quantity", { $ifNull: ["$productInfo.price", 0] } ] }, isOutletA: { $eq: ["$outlet", "Outlet-A"] }, is2018: { $and: [ { $gte: ["$saleDate", ISODate("2018-01-01T00:00:00Z")] }, { $lt: ["$saleDate", ISODate("2019-01-01T00:00:00Z")] } ] } } }, { $facet: { outletARevenue: [ { $match: { isOutletA: true } }, { $group: { _id: null, total: { $sum: "$revenue" } } }, { $project: { _id: 0, "Outlet-A总营收": "$total" } } ], year2018Revenue: [ { $match: { is2018: true } }, { $group: { _id: null, total: { $sum: "$revenue" } } }, { $project: { _id: 0, "2018年总营收": "$total" } } ] } } ])
注意:如果你的
saleDate是字符串类型,需要先通过$toDate转换为Date类型再筛选;如果确定所有销售记录都有对应产品,可以去掉preserveNullAndEmptyArrays: true。
内容的提问来源于stack exchange,提问作者Farid
相关产品推荐
相关产品推荐

