如何使用Aggregation结合Group By与Sum,按时间维度统计有效成交总价
没问题,我来帮你搞定这两个MongoDB聚合的需求,结合你的数据集一步步来解释:
MongoDB聚合:Group By与Sum结合及日期分组统计
1. 基础:Aggregation中Group By与Sum的结合用法
MongoDB的聚合管道里,$group阶段负责实现分组逻辑,$sum操作符用来计算分组内的数值总和。针对你的数据集,需要注意**price字段是字符串类型**,得先用$toDouble转换为数值才能正常求和。
举两个实用的例子:
例1:按status分组,统计不同状态下的Deal总价
db.deals.aggregate([ // 新增字段,把字符串price转成可计算的数值 { $addFields: { priceNum: { $toDouble: "$price" } } }, // 按status分组求和 { $group: { _id: "$status", // 分组键:status的布尔值 totalPrice: { $sum: "$priceNum" }, // 每组的总价总和 dealCount: { $sum: 1 } // 可选:统计每组的Deal数量 } } ])
例2:仅统计所有有效(status=true)Deal的总价
如果不需要分组,只想统计符合条件的全部总和,可以把_id设为null:
db.deals.aggregate([ // 先过滤出有效Deal { $match: { status: true } }, // 转换price为数值 { $addFields: { priceNum: { $toDouble: "$price" } } }, // 不分组,直接统计总和 { $group: { _id: null, totalValidPrice: { $sum: "$priceNum" } } } ])
2. 按年、日、周分组统计当前年份的有效Deal总价
要实现这个需求,需要先过滤出当前年份+status=true的数据,再用日期操作符提取对应的时间维度,最后分组求和。
方式1:用$dateTrunc(MongoDB 5.0+推荐,更简洁)
$dateTrunc可以直接把日期截断到指定精度(年、周、日),非常适合分组场景:
db.deals.aggregate([ // 过滤条件:有效Deal + 当前年份的数据 { $match: { status: true, purchased_at: { $gte: new Date(new Date().getFullYear(), 0, 1), // 当前年份1月1日 $lt: new Date(new Date().getFullYear() + 1, 0, 1) // 下一年1月1日 } } }, // 转换price为数值 { $addFields: { priceNum: { $toDouble: "$price" } } }, // 按「年+周」分组(要按日的话,把unit改成"day"即可) { $group: { _id: { year: { $dateTrunc: { date: "$purchased_at", unit: "year" } }, week: { $dateTrunc: { date: "$purchased_at", unit: "week" } } }, totalPrice: { $sum: "$priceNum" }, dealCount: { $sum: 1 } } }, // 可选:按日期顺序排序 { $sort: { "_id.year": 1, "_id.week": 1 } } ])
方式2:用$year/$week/$dayOfYear(兼容旧版本MongoDB)
如果你的MongoDB版本低于5.0,用日期提取操作符来实现分组:
db.deals.aggregate([ { $match: { status: true, // 直接匹配当前年份 $expr: { $eq: [{ $year: "$purchased_at" }, new Date().getFullYear()] } } }, { $addFields: { priceNum: { $toDouble: "$price" } } }, { $group: { _id: { year: { $year: "$purchased_at" }, week: { $isoWeek: "$purchased_at" }, // ISO标准周(周一为一周开始),用$week则是周日开始 // 按日分组的话替换成:day: { $dateToString: { format: "%Y-%m-%d", date: "$purchased_at" } } }, totalPrice: { $sum: "$priceNum" }, dealCount: { $sum: 1 } } }, { $sort: { "_id.year": 1, "_id.week": 1 } } ])
内容的提问来源于stack exchange,提问作者amit
相关产品推荐
相关产品推荐

