首页/数据/NoSQL 速查/聚合日期函数 $dateToString / $dateTrunc
MongoDB99 条

聚合日期函数 $dateToString / $dateTrunc

日期维度汇总常用:$dateToString 格式化、$dateTrunc 截断到指定时间粒度、$dateDiff 求差,按日按小时都能直接分组。

NoSQL 速查数据更新于 2026-10-13

聚合日期函数是什么

聚合里的日期函数负责把时间戳转成统计维度:$dateToString 按格式化串输出可读日期,$dateTrunc 把时间截断到指定粒度(秒、分、时、天、周、月),$dateDiff 求两个时间之差,$dateAdd 与 $dateSubtract 做日期加减。按天、按小时的报表通用写法是把 $dateTrunc 或 $dateToString 的结果当作 $group 的 _id,再对指标求和计数。

基本信息

分组键写法{ $group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$ts" } } } }
粒度截断{ $dateTrunc: { date: "$ts", unit: "hour" } }
时区参数timezone 可写 "Asia/Shanghai" 或 "+08:00"
默认时区不写 timezone 按 UTC 计算,跨天统计会偏移
求差{ $dateDiff: { startDate: "$a", endDate: "$b", unit: "second" } }

典型使用场景

  • 日活与趋势报表:按自然日分组计数,输出折线图数据
  • 月度归档:$dateTrunc 到 month 得到月度汇总,供对账使用
  • 履约时长统计:$dateDiff 算下单到发货之间的小时数
  • 同比环比:用 $dateAdd 与 $dateSubtract 取去年同期的时间区间
  • 补零与对齐:把时间桶作为维度,应用侧补齐空缺日期避免折线跳变

按自然日聚合

按自然日聚合
db.orders.aggregate([
  { $match: { ts: { $gte: ISODate("2026-01-01T00:00:00Z"), $lt: ISODate("2026-02-01T00:00:00Z") } } },
  { $group: {
      _id: { $dateToString: { format: "%Y-%m-%d", date: "$ts", timezone: "+08:00" } },  // 东八区自然日
      orders: { $sum: 1 },
      total: { $sum: "$amount" }
  } },
  { $sort: { _id: 1 } }
])

// 换成截断到小时,_id 是日期对象,可继续参与日期运算
// { $group: { _id: { $dateTrunc: { date: "$ts", unit: "hour", timezone: "+08:00" } } } }

四个函数怎么选

表达式返回适用
$dateToString格式化字符串直接给前端展示的日期标签
$dateTrunc日期对象结果还要继续做日期运算时
$dateDiff整数算时长、账期天数
$dateAdd / $dateSubtract日期对象取上一周期做对比
不写 timezone 就按 UTC 计算,中国区报表会把凌晨 8 点前的数据算进前一天;报表口径应把时区固定在代码或配置里,避免各处写法不一致。
$dateTrunc 支持 week 与 month 粒度,但周起点规则与时区相关,跨系统对账前先对齐口径。

求时长与取上周期

求时长与取上周期
// 履约时长:下单到发货的小时数
{ $addFields: { hours: { $dateDiff: { startDate: "$created", endDate: "$shipTime", unit: "hour" } } } }

// 上月同期区间,用于环比
{ $match: { ts: {
    $gte: { $dateSubtract: { startDate: "$$NOW", unit: "month", amount: 1 } },
    $lt: "$$NOW"
} } }
用 $$NOW 这类系统变量拿当前时刻时,整条管道只在开始执行时求值一次,适合做「最近 N 天」的口径,但结果会随执行时间变化,做报表快照时应改为传入固定时间参数。
$dateToString 的 format 除 %Y-%m-%d 外还支持 %H:%M:%S、ISO 周相关的格式符等,按官方格式符表选择;写错格式符通常得到字面输出而不是报错,上线前要先用几条真实数据验证。

易错点

  • 聚合时区不写会差 8 小时,明细与汇总对不上账
  • 对字符串类型的日期字段直接调 $dateToString 会报错,需要先用 $toDate 转换
  • 按周分组时各数据库的周起点不同(周日或周一),跨库核对前先统一
  • $dateDiff 的起点终点写反会得到负数,边界是开区间还是闭区间要按官方文档确认

数据来源与参考

  • MongoDB Manual: $dateToString
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌