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

MongoDB $dateTrunc聚合算子未返回预期结果问题咨询

问题描述

我在MongoDB时序集合上使用$dateTrunc算子,想要将2024-12-01至2024-12-07的时序数据分组到同一个数据桶中。

我的聚合管道如下:

[
  {
    $match: {
      timestamp: {
        $gte: ISODate('2024-12-01'),
        $lte: ISODate('2024-12-07'),
      },
    }
  },
  {
    $group: {
      _id: {
        timestamp: {
          $dateTrunc: {
            date: "$timestamp",
            unit: 'day',
            binSize: 7,
          },
        }
      },
      count: {
        $sum: 1
      }
    }
  },
  {
    $set: {
      timestamp: "$_id.timestamp"
    }
  },
  {
    $sort: {
      timestamp: 1
    }
  }
]

实际得到的结果:

[
  {
    "_id": {
      "timestamp": {
        "$date": "2024-11-30T00:00:00.000Z"
      }
    },
    "count": 719,
    "timestamp": {
      "$date": "2024-11-30T00:00:00.000Z"
    }
  },
  {
    "_id": {
      "timestamp": {
        "$date": "2024-12-07T00:00:00.000Z"
      }
    },
    "count": 116,
    "timestamp": {
      "$date": "2024-12-07T00:00:00.000Z"
    }
  }
]

我期望返回一个汇总这7天数据的结果(时间戳从2024-12-01开始),但实际结果不符合预期。

时序集合信息补充:

  • timeField -> timestamp
  • metaField -> tags
  • expireAfterSeconds -> undefined
  • granularity -> Hours
  • bucketMaxSpanSeconds -> undefined

解决方案

问题核心是$dateTrunc默认从Unix纪元(1970-01-01)开始计算数据桶的起始点,而非你指定的查询起始日期2024-12-01。2024-12-01往前最近的7天整桶起始点是2024-11-30,所以12月1日-6日的数据会被归入这个桶,12月7日的数据则进入下一个起始于2024-12-07的桶。

要实现从2024-12-01开始的7天分组,给$dateTrunc加上startAt参数,强制桶的起始点对齐目标日期即可:

修改后的聚合管道:

[
  {
    $match: {
      timestamp: {
        $gte: ISODate('2024-12-01'),
        $lte: ISODate('2024-12-07'),
      },
    }
  },
  {
    $group: {
      _id: {
        timestamp: {
          $dateTrunc: {
            date: "$timestamp",
            unit: 'day',
            binSize: 7,
            startAt: ISODate('2024-12-01') // 指定桶的起始基准日期
          },
        }
      },
      count: {
        $sum: 1
      }
    }
  },
  {
    $set: {
      timestamp: "$_id.timestamp"
    }
  },
  {
    $sort: {
      timestamp: 1
    }
  }
]

如果需要动态对齐查询起始日期(而非固定2024-12-01),可以先获取数据集的最小时间戳,再将其作为startAt的值:

[
  {
    $match: {
      timestamp: {
        $gte: ISODate('2024-12-01'),
        $lte: ISODate('2024-12-07'),
      },
    }
  },
  {
    $group: {
      _id: null,
      minTimestamp: { $min: "$timestamp" },
      docs: { $push: "$$ROOT" }
    }
  },
  {
    $unwind: "$docs"
  },
  {
    $group: {
      _id: {
        timestamp: {
          $dateTrunc: {
            date: "$docs.timestamp",
            unit: 'day',
            binSize: 7,
            startAt: "$minTimestamp"
          },
        }
      },
      count: { $sum: 1 }
    }
  },
  {
    $set: {
      timestamp: "$_id.timestamp"
    }
  },
  {
    $sort: {
      timestamp: 1
    }
  }
]

以上两种方式都能确保查询范围内的所有数据被归入同一个以2024-12-01为起始点的7天桶中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 10:58:18