如何在MongoDB中用mongoose统计指定月份每日不同状态的任务数
实现方案
你可以通过MongoDB聚合管道完成该统计需求,完整实现代码如下:
const mongoose = require('mongoose'); // 你定义的Task模型 const Task = mongoose.model('Task', taskSchema); const getMonthlyTaskStats = async (year, month) => { // 构造目标月份的起止时间,注意JS月份从0开始计数 const startDate = new Date(year, month - 1, 1); const endDate = new Date(year, month, 1); return await Task.aggregate([ // 过滤出目标月份的所有任务,减少后续计算量 { $match: { created_at: { $gte: startDate, $lt: endDate } } }, // 将Date类型的创建时间转为你需要的 DD-MM-YYYY 字符串格式 { $addFields: { formattedDate: { $dateToString: { format: "%d-%m-%Y", date: "$created_at", // 如需适配时区可新增该参数,示例为中国时区 // timezone: "Asia/Shanghai" } } } }, // 按「日期+状态」分组,统计每个日期下每个状态的任务数量 { $group: { _id: { date: "$formattedDate", status: "$status" }, count: { $sum: 1 } } }, // 再按日期分组,把同一日期的所有状态统计值合并为数组 { $group: { _id: "$_id.date", statusList: { $push: { k: "$_id.status", v: "$count" } } } }, // 补全所有状态的默认值,无数据的状态自动设为0 { $addFields: { statusMap: { $arrayToObject: { $concatArrays: [ "$statusList", // 这里的三个状态为你需要统计的所有枚举值,顺序可自定义 [{k: "pending", v: 0}, {k: "missed", v: 0}, {k: "completed", v: 0}] ] } } } }, // 调整为你要求的输出结构,日期作为键,统计对象作为值 { $replaceRoot: { newRoot: { $arrayToObject: [ [{k: "$_id", v: "$statusMap"}] ] } } } ]); }; // 调用示例:查询2021年6月的统计结果 const juneStats = await getMonthlyTaskStats(2021, 6);
补充说明
如果你的状态枚举值后续有新增,只需要修改$concatArrays里的默认状态数组即可,不需要调整其他逻辑。聚合返回的结果和你要求的结构完全一致,不需要额外做数据处理。
内容的提问来源于stack exchange,提问作者Uday Mittal
相关产品推荐
相关产品推荐

