如何在MongoDB中按月份聚合指定日期区间内的待办事项数据?
解决MongoDB按月份统计待办事项数量的问题
我来帮你调整聚合管道,让它能分别统计3月和4月的待办事项数量。你的原代码只计算了指定日期范围内的总数,没有按月份拆分,所以我们需要修改几个关键步骤:
核心思路
- 先过滤出
type为"A"的用户文档; - 展开
todos数组,让每个待办事项成为独立的文档,方便按月份统计; - 筛选出创建时间在
fromDate到toDate之间的待办; - 提取每个待办的创建月份;
- 按月份分组统计数量,最后整理成易读的格式。
完整聚合代码
方式一:返回分月份的列表结果
const result = await Todos.aggregate([ // 过滤type为"A"的用户 { $match: { type: 'A' } }, // 展开todos数组,每个todo单独成为一条文档 { $unwind: '$todos' }, // 筛选出日期在指定范围内的todo { $match: { $expr: { $and: [ { $gte: [{ $toDate: '$todos.createdAt' }, { $toDate: fromDate }] }, { $lte: [{ $toDate: '$todos.createdAt' }, { $toDate: toDate }] } ] } } }, // 提取todo创建时间的月份(3代表3月,4代表4月) { $addFields: { todoMonth: { $month: { $toDate: '$todos.createdAt' } } } }, // 按月份分组,统计每个月的todo数量 { $group: { _id: '$todoMonth', count: { $sum: 1 } } }, // 转换为更直观的格式,把数字月份转成英文名称 { $project: { _id: 0, month: { $switch: { branches: [ { case: { $eq: ['$_id', 3] }, then: 'March' }, { case: { $eq: ['$_id', 4] }, then: 'April' } ], default: 'Other' } }, todoCount: '$count' } } ])
执行后会得到类似这样的结果:
[ { "month": "March", "todoCount": 15 }, { "month": "April", "todoCount": 22 } ]
方式二:返回包含两个统计值的单个对象
如果你希望结果是一个包含3月和4月数量的对象,可以在上面的基础上增加两个阶段:
// 在上述$project之后添加: { $group: { _id: null, marchCount: { $sum: { $cond: [{ $eq: ['$month', 'March'] }, '$todoCount', 0] } }, aprilCount: { $sum: { $cond: [{ $eq: ['$month', 'April'] }, '$todoCount', 0] } } } }, { $project: { _id: 0 } }
最终结果会是:
{ "marchCount": 15, "aprilCount": 22 }
为什么原代码不符合需求?
你的原代码通过$filter筛选出每个用户符合日期范围的todos,然后用$size计算每个用户的符合数量,最后$group求和得到总数,但整个过程没有对月份进行拆分统计,所以无法区分3月和4月的数量。通过$unwind展开数组后,我们才能对每个todo单独处理,按月份分组统计。
内容的提问来源于stack exchange,提问作者mustafa shaikh
相关产品推荐
相关产品推荐

