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

MongoDB:如何从首个文档的createdAt按7天分组?及$dateTrunc疑问

问题分析与解决方案

问题2:$dateTrunc返回2022-10-29的原因

MongoDB的$dateTrunc并非以输入日期为基准往前推7天,而是从**纪元时间(1970-01-01)**开始,按指定的binSize(7天)划分固定时间桶,返回输入日期所在桶的起始时间。

计算验证:2022-11-02所在的7天桶区间是2022-10-29至2022-11-05(2022-10-29 + 7天),因此$dateTrunc返回该桶的起始时间2022-10-29,而非预期的2022-10-25。

问题1:实现动态往后7天分组的方案

$dateTrunc的固定分桶逻辑无法满足“以实际存在的文档日期为起点,往后7天内的文档归为一组”的需求,需要通过聚合管道结合窗口函数实现动态分组:

完整聚合代码

db.xxxx.aggregate([
  // 按日期升序排序,确保文档顺序正确
  { $sort: { orderDate: 1 } },
  // 使用窗口函数计算每个文档的分组起始日期
  {
    $setWindowFields: {
      partitionBy: null, // 全局处理所有文档
      sortBy: { orderDate: 1 },
      output: {
        groupStartDate: {
          $reduce: {
            input: "$orderDate",
            initialValue: {
              currentStart: { $first: "$orderDate" },
              result: { $first: "$orderDate" }
            },
            in: {
              $let: {
                vars: {
                  // 当前分组的结束时间(起点+7天)
                  groupEnd: { $add: ["$$value.currentStart", 7 * 24 * 60 * 60 * 1000] }
                },
                in: {
                  currentStart: {
                    // 若当前文档日期超过分组结束时间,更新分组起点为当前日期
                    $cond: {
                      if: { $gt: ["$$this", "$$groupEnd"] },
                      then: "$$this",
                      else: "$$value.currentStart"
                    }
                  },
                  result: {
                    $cond: {
                      if: { $gt: ["$$this", "$$groupEnd"] },
                      then: "$$this",
                      else: "$$value.result"
                    }
                  }
                }
              }
            }
          },
          window: { documents: ["unbounded", "current"] }
        }
      }
    }
  },
  // 按分组起始日期聚合文档
  {
    $group: {
      _id: "$groupStartDate",
      documents: { $push: "$$ROOT" },
      // 计算分组的结束日期(起点+7天)
      groupEndDate: { $max: { $add: ["$groupStartDate", 7 * 24 * 60 * 60 * 1000] } }
    }
  },
  // 可选:格式化日期为字符串,便于阅读
  {
    $project: {
      _id: 0,
      groupStartDate: { $dateToString: { format: "%Y-%m-%d", date: "$_id" } },
      groupEndDate: { $dateToString: { format: "%Y-%m-%d", date: "$groupEndDate" } },
      documents: 1
    }
  }
])

逻辑说明

  1. 排序:先按日期升序排列文档,确保从最早的文档开始处理。
  2. 动态计算分组起点:通过$setWindowFields和$reduce遍历每个文档,判断当前文档是否超出上一个分组的7天范围:
    • 若未超出,沿用之前的分组起点;
    • 若超出,将当前文档的日期设为新的分组起点。
  3. 分组聚合:按计算出的分组起点聚合文档,同时计算每个分组的结束日期。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 14:36:10