You need to enable JavaScript to run this app. MongoDB新手求助:实现每日各状态文档计数,补全无数据日期零值结果
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB新手求助:实现每日各状态文档计数,补全无数据日期零值结果

MongoDB每日分状态计数(含零值补全)实现方案

核心实现思路

MongoDB原生聚合默认只会输出存在文档的日期/状态组合,不会自动补全缺失的零值,因此整体方案拆为3步落地:

  • 先根据现有文档的日期范围,生成覆盖全时间段的连续日期骨架
  • 聚合现有文档,按「日期+状态」维度统计实际文档数
  • 将日期骨架与实际统计结果做关联匹配,对没有匹配到的日期、状态项自动补计数0

可直接运行的聚合查询

注意:执行前请把代码中两处your_collection_name替换为你实际的业务集合名称

db.your_collection_name.aggregate([
  // 提取集合内所有日期的边界范围,作为后续生成连续日期的依据
  {
    $group: {
      _id: null,
      minDate: { $min: "$date" },
      maxDate: { $max: "$date" }
    }
  },
  // 生成连续日期骨架,适配示例中"月/日"的字符串日期格式
  {
    $project: {
      dateSkeleton: {
        $map: {
          input: {
            $range: [
              // 解析字符串里的月份数值作为序列起点
              { $toInt: { $first: { $split: ["$minDate", "/"] } } },
              // 解析字符串里的月份数值作为序列终点,+1是因为$range左闭右开
              { $add: [ { $toInt: { $first: { $split: ["$maxDate", "/"] } } }, 1 ] }
            ]
          },
          as: "monthItem",
          // 拼接成和原始格式一致的日期字符串
          in: { $concat: [ { $toString: "$$monthItem" }, "/1" ] }
        }
      }
    }
  },
  // 把数组形式的日期骨架拆成单条日期记录,作为后续补零的基准
  { $unwind: "$dateSkeleton" },
  { $project: { _id: 0, date: "$dateSkeleton" } },
  // 关联实际文档的分状态统计结果
  {
    $lookup: {
      from: "your_collection_name",
      pipeline: [
        // 第一层分组:按日期+状态维度统计实际文档数量
        {
          $group: {
            _id: { date: "$date", status: "$status" },
            count: { $sum: 1 }
          }
        },
        // 第二层分组:按日期把所有状态的计数聚合成映射表
        {
          $group: {
            _id: "$_id.date",
            statusCountMap: {
              $push: { k: "$_id.status", v: "$count" }
            }
          }
        }
      ],
      as: "statResult"
    }
  },
  // 匹配对应状态的计数,无匹配则补0
  {
    $project: {
      _id: 0,
      date: 1,
      statusA: {
        $ifNull: [
          { $getField: { field: "v", input: { $arrayElemAt: [ "$statResult.statusCountMap", { $indexOfArray: [ "$statResult.statusCountMap.k", "A" ] } ] } } },
          0
        ]
      },
      statusB: {
        $ifNull: [
          { $getField: { field: "v", input: { $arrayElemAt: [ "$statResult.statusCountMap", { $indexOfArray: [ "$statResult.statusCountMap.k", "B" ] } ] } } },
          0
        ]
      }
    }
  }
])

按需调整指引

  • 状态枚举扩展:如果业务中除了A、B还有其他固定状态,只需在最后$project阶段照着statusA、statusB的写法,新增对应状态的取值判断即可,没有匹配到的会自动补0
  • 日期格式适配:如果你的date字段不是示例里的短字符串格式,而是标准ISODate类型,把生成连续日期骨架的逻辑替换为:先用$dateDiff计算最早和最晚日期的天数差,再通过$dateAdd逐天生成连续的标准日期对象即可
  • 自定义时间范围:如果不需要自动识别集合内的日期范围,而是要固定统计某段时间(比如1月整月),可以跳过第一步提取min/max日期的逻辑,直接在生成日期骨架的$range阶段传入你指定的时间边界值

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.07 08:45:08