如何用MongoDB聚合按门店按月统计总营收及商品均价?
问题分析与解决方案
现有代码的问题
- 未处理嵌套数组:
price和quantity是items数组内的字段,直接引用会导致计算错误,必须先展开数组。 - 分组维度错误:未按
store和月份分组,无法得到各门店每月的统计结果。 - 日期格式不符:使用
%Y-%m-%d会生成带具体日期的格式,不符合需求的YYYY-MM月份格式。 - 排序规则错误:需求是按门店、月份升序,现有代码按总营收降序排序。
- 均价计算逻辑错误:未针对展开后的商品条目计算平均价格。
正确聚合代码
db.sales.aggregate([ // 展开items数组,将每个商品转换为独立文档 { $unwind: "$items" }, // 按门店+月份分组,计算总营收与均价 { $group: { _id: { store: "$store", month: { $dateToString: { format: "%Y-%m", date: "$date" } } }, totalRevenue: { $sum: { $multiply: ["$items.quantity", "$items.price"] } }, averagePrice: { $avg: "$items.price" } } }, // 调整字段结构,匹配期望输出 { $project: { _id: 0, store: "$_id.store", month: "$_id.month", totalRevenue: 1, averagePrice: 1 } }, // 按门店、月份升序排序 { $sort: { store: 1, month: 1 } } ])
代码阶段说明
$unwind阶段:拆分items数组,将每个商品条目转为独立文档,确保能单独计算每个商品的营收和价格。$group阶段:- 以
store和YYYY-MM格式的月份作为分组键,保证统计维度为「门店-月度」。 totalRevenue累加所有商品的营收(数量×单价)。averagePrice计算所有商品条目的单价平均值。
- 以
$project阶段:将分组结果中的嵌套字段展开为顶层字段,移除冗余的_id,匹配期望的输出结构。$sort阶段:按门店名称、月份升序排序,满足需求的排序规则。
可选:加权均价计算
如果需要按「总营收÷总销量」计算加权均价,可修改$group和$project阶段:
{ $group: { _id: { store: "$store", month: { $dateToString: { format: "%Y-%m", date: "$date" } } }, totalRevenue: { $sum: { $multiply: ["$items.quantity", "$items.price"] } }, totalQuantity: { $sum: "$items.quantity" } } }, { $project: { _id: 0, store: "$_id.store", month: "$_id.month", totalRevenue: 1, averagePrice: { $divide: ["$totalRevenue", "$totalQuantity"] } } }
内容的提问来源于stack exchange,提问作者JS Noob
相关产品推荐
相关产品推荐

