You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为MongoDB聚合设置默认值?补全无维修日期计数零值

解决MongoDB聚合查询补全无维修记录日期count为0的问题

需求:获取指定时间段内的每日维修统计数据,无维修记录的日期需将count字段默认设为0。当前聚合查询仅返回存在维修记录的日期,示例输出如下:

[
  { day: 21, month: 10, year: 2022, count: 2 },
  { day: 28, month: 10, year: 2022, count: 1 },
  { day: 24, month: 10, year: 2022, count: 2 }
]

现有聚合查询代码:

const result = await Repair.aggregate([
    {
        $match: {
            createdDate: {
                $gte: new Date(fromDate),
                $lte: new Date(toDate),
            },
        },
    },
    {
        $group: {
            _id: {
                day: "$day",
                year: "$year",
                month: "$month",
            },
            count: {
                $sum: 1,
            },
        },
    },
    {
        $project: {
            _id: 0,
            day: "$_id.day",
            month: "$_id.month",
            year: "$_id.year",
            count: "$count",
        },
    },
]);

修改方案

MongoDB聚合本身无法直接生成日期序列,需先构造出查询区间内的所有日期,再与原统计结果做左外连接,补全无数据日期的count为0。

完整修改后的代码

// 计算日期区间的天数差,生成所有日期的基础数据
const start = new Date(fromDate);
const end = new Date(toDate);
const daysDiff = Math.ceil((end - start) / (1000 * 60 * 60 * 24)) + 1;

const result = await Repair.aggregate([
    // 1. 生成目标区间内的所有日期文档
    {
        $documents: Array.from({ length: daysDiff }, (_, i) => {
            const date = new Date(start);
            date.setDate(start.getDate() + i);
            return {
                year: date.getFullYear(),
                month: date.getMonth() + 1, // 月份从1开始匹配原数据格式
                day: date.getDate()
            };
        })
    },
    // 2. 左连接原维修统计结果
    {
        $lookup: {
            from: "repairs", // 替换为你的Repair集合实际名称
            let: {
                targetYear: "$year",
                targetMonth: "$month",
                targetDay: "$day"
            },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                { $eq: ["$year", "$$targetYear"] },
                                { $eq: ["$month", "$$targetMonth"] },
                                { $eq: ["$day", "$$targetDay"] },
                                { $gte: ["$createdDate", new Date(fromDate)] },
                                { $lte: ["$createdDate", new Date(toDate)] }
                            ]
                        }
                    }
                },
                { $count: "count" }
            ],
            as: "repairStats"
        }
    },
    // 3. 处理连接结果,补全零值
    {
        $project: {
            year: 1,
            month: 1,
            day: 1,
            count: {
                $ifNull: [{ $arrayElemAt: ["$repairStats.count", 0] }, 0]
            }
        }
    },
    // 4. 按日期排序(可选,让结果更规整)
    {
        $sort: { year: 1, month: 1, day: 1 }
    }
]);

方案说明

  1. 生成日期序列:通过$documents构造出查询区间内的每一天的year、month、day文档,确保所有日期都被覆盖。
  2. 左连接统计数据:用$lookup将日期序列与维修集合的统计结果关联,只匹配对应日期的维修记录。
  3. 补全零值:用$ifNull和$arrayElemAt提取统计结果的count,若没有匹配结果则设为0。
  4. 排序(可选):最后按日期升序排列,让结果更符合阅读习惯。

内容的提问来源于stack exchange,提问作者Ali Parlatti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 19:00:32