聚合运算符$dateTrunc
用于将日期字段的时间部分截断到指定的单位。
$dateTrunc 可以用于以下场景:
- 按指定的时间单位对日期进行截断:这意味着可以将日期字段舍入到最近的单位,如天、小时、分钟等。例如,将所有记录舍入到最近的小时。
- 在聚合查询中按截断后的日期进行分组:当结合
$group
操作符使用时,dateTrunc 将销售日期截断到月份,然后再使用$group
进行分组和求和。 - 精确控制日期字段的显示和比较:通过截断日期,可以确保在进行比较或排序时,只考虑日期的特定部分,从而得到更精确的结果。
- 处理时间序列数据:在处理时间序列数据时,
$dateTrunc
可以用来更好地分析和汇总数据,比如计算特定时间段内的平均销售额或用户活跃度等。
语法
{
$dateTrunc: {
date: <Expression>,
unit: <Expression>,
binSize: <Expression>,
timezone: <tzExpression>,
startOfWeek: <Expression>
}
}
字段说明
字段 | 是否必须 | 描述 |
| 是 | 要截断的日期(UTC),可以是日期、时间戳或对象Id表达式 |
| 是 | 要增加的时间的单位,单位可以是能被解析为下列值的表达式: |
| 否 | 时间数值,以表达式形式指定,必须是非零正数。默认值为 1。 |
| 否 | 执行操作的时区, |
| 否 | 指定周开始的天,只有当单位是周时可用,缺省为 |
使用
- 除
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
}
]