聚合运算符$dateTrunc
用于将日期字段的时间部分截断到指定的单位。
$dateTrunc 可以用于以下场景:
- 按指定的时间单位对日期进行截断:这意味着可以将日期字段舍入到最近的单位,如天、小时、分钟等。例如,将所有记录舍入到最近的小时。
- 在聚合查询中按截断后的日期进行分组:当结合
$group
操作符使用时, d a t e T r u n c 可以帮助你按照截断后的日期进行分组,这对于生成时间序列数据的报告非常有用。例如,要统计每个月的销售总额,可以先使用 dateTrunc 可以帮助你按照截断后的日期进行分组,这对于生成时间序列数据的报告非常有用。例如,要统计每个月的销售总额,可以先使用 dateTrunc可以帮助你按照截断后的日期进行分组,这对于生成时间序列数据的报告非常有用。例如,要统计每个月的销售总额,可以先使用dateTrunc 将销售日期截断到月份,然后再使用$group
进行分组和求和。 - 精确控制日期字段的显示和比较:通过截断日期,可以确保在进行比较或排序时,只考虑日期的特定部分,从而得到更精确的结果。
- 处理时间序列数据:在处理时间序列数据时,
$dateTrunc
可以用来更好地分析和汇总数据,比如计算特定时间段内的平均销售额或用户活跃度等。
语法
{$dateTrunc: {date: <Expression>,unit: <Expression>,binSize: <Expression>,timezone: <tzExpression>,startOfWeek: <Expression>}
}
字段说明
字段 | 是否必须 | 描述 |
---|---|---|
date | 是 | 要截断的日期(UTC),可以是日期、时间戳或对象Id表达式 |
unit | 是 | 要增加的时间的单位,单位可以是能被解析为下列值的表达式:year 、quarter 、week 、month 、day 、hour 、minute 、second 、millisecond ,与binSize 一起指定时间段 |
binSize | 否 | 时间数值,以表达式形式指定,必须是非零正数。默认值为 1。 |
timezone | 否 | 执行操作的时区,<tzExpression> 必须是能被解析为奥尔森时区标识符格式的字符串或UTC偏移量,如果timezone 不指定,返回值显示为UTC |
startOfWeek | 否 | 指定周开始的天,只有当单位是周时可用,缺省为Sunday ,startOfWeek 可以是一个表达式,但必须能够被解析为:monday (或 mon) 、tuesday (或 tue) 、wednesday (或 wed) 、thursday (或 thu) 、friday (或 fri) 、saturday (或 sat) 、sunday (或 sun) |
使用
- 除
startOfWeek
字段外的其他字段如果缺失或为空,亦或者unit
为week
并且startOfWeek
缺失或为null
,直接返回null
。 - 对于1583年之前的日期使用预推公历。
- 计算夏令时,不计算闰秒。
binSize和unit字段
-
binSize
和unit
一起用于指定$dateTrunc
计算的时间段,例如:- 若
binSize
为1
且unit
为hour
,则时间段为1小时,对于日期2021-03-20T11:30:05Z
,$dateTrunc
返回2021-03-20T11:00:00Z
。 - 若
binSize
为2
且unit
为hour
,则时间段为2小时,对于日期2021-03-20T11:30:05Z
,$dateTrunc
返回2021-03-20T10:00:00Z
。
- 若
-
$dateTrunc
截取以unit
为单位,binSize
个时间段,时段开始于基准日期,并且由unit
决定:- 如果
unit
是除week
外的其他值,$dataTrunc
使用参考日期,拿2000-01-01T00:00:00.00Z
,例来说,如果binSize
为10,并且单位unit
为年,示例的时间段为:2000-01-01T00:00:00.00Z
2010-01-01T00:00:00.00Z
2020-01-01T00:00:00.00Z
- 如果
unit
的值是week
,则$dateTrunc
使用一周中的首日作为基准日期,可能会大于等于2000-01-01
,首日由startOfWeek
指定。
- 如果
-
$dateTrunc
以ISODate格式返回日期时段的下边界,如果binSize
的值为1,$dateTrunc
将unit
指定单位后面的值设置为0,其余部分保持不变。 -
当unit为:
year
,以date
所在年度1月1日为基准quarter
,以date
所属季度的第一天为基准month
,以date
所属月份的第一天为基准week
,以date
所在周中startOfWeek
指定的那一天为基准,缺省为Sunday
day
,以date
为基准hour
,以date
的小时为基准minute
,以date
的分钟为基准second
,以date
的秒为基准
unit和startOfWeek字段
- 如果
unit
的值不等于week
,startOfWeek
将被忽略 - 如果
unit
的值等于week
,当指定startOfWeek
时,使用startOfWeek
指定值作为周的第一天。否则,使用Sunday
。
举例
创建一个包含加利福尼亚州(CA)和华盛顿州(WA)蛋糕销售记录的集合cakeSales
:
db.cakeSales.insertMany( [{ _id: 0, type: "chocolate", orderDate: new Date("2020-05-18T14:10:30Z"),state: "CA", price: 13, quantity: 120 },{ _id: 1, type: "chocolate", orderDate: new Date("2021-03-20T11:30:05Z"),state: "WA", price: 14, quantity: 140 },{ _id: 2, type: "vanilla", orderDate: new Date("2021-01-11T06:31:15Z"),state: "CA", price: 12, quantity: 145 },{ _id: 3, type: "vanilla", orderDate: new Date("2020-02-08T13:13:23Z"),state: "WA", price: 13, quantity: 104 },{ _id: 4, type: "strawberry", orderDate: new Date("2019-05-18T16:09:01Z"),state: "CA", price: 41, quantity: 162 },{ _id: 5, type: "strawberry", orderDate: new Date("2019-01-08T06:12:03Z"),state: "WA", price: 43, quantity: 134 }
] )
在$project
管道阶段截取订单日期
db.cakeSales.aggregate( [{$project: {_id: 1,orderDate: 1,truncatedOrderDate: {$dateTrunc: {date: "$orderDate", unit: "week", binSize: 2,timezone: "America/Los_Angeles", startOfWeek: "Monday"}}}}
] )
本例中:
$project
将文档的_id
、orderDate
和truncatedOrderDate
字段输出到下一阶段$dateTrunc
使用binSize
为2,unit
为week
,时区为America/Los_Angeles
,startOfWeek
为Monday
对orderDate
字段进行截取
结果如下:
[{_id: 0,orderDate: ISODate("2020-05-18T14:10:30.000Z"),truncatedOrderDate: ISODate("2020-05-11T07:00:00.000Z")},{_id: 1,orderDate: ISODate("2021-03-20T11:30:05.000Z"),truncatedOrderDate: ISODate("2021-03-15T07:00:00.000Z")},{_id: 2,orderDate: ISODate("2021-01-11T06:31:15.000Z"),truncatedOrderDate: ISODate("2021-01-04T08:00:00.000Z")},{_id: 3,orderDate: ISODate("2020-02-08T13:13:23.000Z"),truncatedOrderDate: ISODate("2020-02-03T08:00:00.000Z")},{_id: 4,orderDate: ISODate("2019-05-18T16:09:01.000Z"),truncatedOrderDate: ISODate("2019-05-13T07:00:00.000Z")},{_id: 5,orderDate: ISODate("2019-01-08T06:12:03.000Z"),truncatedOrderDate: ISODate("2019-01-07T08:00:00.000Z")}
]
在$group阶段对分组日期字段进行截取
下面的例子在$group
阶段使用dateTrunc
对蛋糕销售记录的orderDate
值,按照6个月进行截断,然后进行分组汇总:
db.cakeSales.aggregate( [{$group: {_id: {truncatedOrderDate: {$dateTrunc: {date: "$orderDate", unit: "month", binSize: 6}}},sumQuantity: { $sum: "$quantity" }}}
] )
在本例中:
$group
将truncatedOrderDate
作为_id
字段对cakeSales
文档进行分组,使用$sum
对分组内的quantity
字段值进行合计$dateTrunc
以6个月的间隔对orderDate
进行截取
结果如下:
[{_id: { truncatedOrderDate: ISODate("2020-01-01T00:00:00.000Z") },sumQuantity: 224},{_id: { truncatedOrderDate: ISODate("2021-01-01T00:00:00.000Z") },sumQuantity: 285},{_id: { truncatedOrderDate: ISODate("2019-01-01T00:00:00.000Z") },sumQuantity: 296}
]