You need to enable JavaScript to run this app. MongoDB按日期分组聚合如何补全查询范围内的缺失日期
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB按日期分组聚合如何补全查询范围内的缺失日期

解决方案

可以通过调整聚合管道实现目标,针对MongoDB不同版本有两种实现方式:

方案1:MongoDB 5.1及以上版本(推荐)

使用MongoDB原生提供的$densify聚合操作符,它可以自动补全指定范围内的缺失序列,你可以直接在原有管道基础上追加$densify阶段,调整后的完整管道如下:

[
  {
    $match: {
      orderDate: {
        $gte: new Date('2021-08-01T00:00:00+05:30'),
        $lte: new Date('2021-08-06T23:59:59+05:30'),
      }
    }
  },
  {
    $group: {
      _id: {
        $dateToString: {
          format: '%Y-%m-%d',
          date: '$orderDate',
        }
      }
    }
  },
  // 新增:补全缺失的日期
  {
    $densify: {
      field: "_id",
      range: {
        step: 1,
        unit: "day",
        bounds: [
          ISODate("2021-08-01T00:00:00+05:30"),
          ISODate("2021-08-06T23:59:59+05:30")
        ]
      }
    }
  },
  // 可选:如果需要统一把_id转为字符串格式,可以加这个阶段
  {
    $project: {
      _id: {
        $dateToString: {
          format: "%Y-%m-%d",
          date: "$_id"
        }
      }
    }
  }
]

运行后就会自动补全2021-08-03、2021-08-06两条记录,如果你还有其他统计字段(比如订单数、销售额等),缺失的日期对应的统计字段会自动赋值为null,你可以后续追加$addFields阶段把null替换为0。

方案2:MongoDB 5.0及以下版本

如果你的MongoDB版本不支持$densify,可以用$documents配合$dateDiff生成完整的日期序列,再和原有分组结果做左连接,实现逻辑如下:

[
  // 第一步:先做原有分组统计
  {
    $match: {
      orderDate: {
        $gte: new Date('2021-08-01T00:00:00+05:30'),
        $lte: new Date('2021-08-06T23:59:59+05:30'),
      }
    }
  },
  {
    $group: {
      _id: {
        $dateToString: {
          format: '%Y-%m-%d',
          date: '$orderDate',
        }
      }
    }
  },
  // 第二步:把分组结果合并为一个数组
  {
    $group: {
      _id: null,
      existDates: { $push: "$$ROOT" }
    }
  },
  // 第三步:生成查询范围内的完整日期序列
  {
    $addFields: {
      allDates: {
        $map: {
          input: { $range: [0, 6] }, // 6是日期跨度的天数,这里从8.1到8.6共6天
          in: {
            _id: {
              $dateToString: {
                format: "%Y-%m-%d",
                date: {
                  $add: [ new Date('2021-08-01T00:00:00+05:30'), { $multiply: ["$$this", 86400000] } ]
                }
              }
            }
          }
        }
      }
    }
  },
  // 第四步:合并两个数组,去重
  {
    $project: {
      result: {
        $setUnion: ["$allDates", "$existDates"]
      }
    }
  },
  // 第五步:拆分数组返回单条记录
  {
    $unwind: "$result"
  },
  {
    $replaceRoot: { newRoot: "$result" }
  }
]

注意:这个方案里$range的第二个参数需要你根据传入的日期范围动态计算总天数,也可以用$dateDiff动态计算,避免硬编码。

内容的提问来源于stack exchange,提问作者Mohamed Imran

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 21:42:01