mongodb 聚合截断日期函数?

yv5phkfx  于 2023-03-29  发布在  Go
关注(0)|答案(4)|浏览(168)

我以前用过一堆SQL数据库;例如Postgres和BigQuery,它们具有日期截断功能(例如:date_truncTIMESTAMP_TRUNC)。
mongodb是否有DATE_TRUNC函数?
我已经找到了$trunc运算符,但它只适用于数字。
我想要一个DATE_TRUNC函数将给定的Date(其他SQL数据库中的时间戳类型)截断到特定的边界,例如年初,月初,小时的开始,可以通过获取其年,月,日期,小时来组成新的Date。
有没有人有一些变通的方法?特别是对于开始的时刻,一周,和开始的ISOWEEK,有没有人有一个很好的变通方法?

0ejtzxu1

0ejtzxu11#

可以组合$dateToParts$dateFromParts

db.getCollection("data").aggregate([
  {"$addFields": {
     "dateVarFull": {"$dateToParts": {date: {"$toDate" : "2020-08-27T13:00:00Z"}}}
  }},
  {"$addFields": {
    "dateVarTrunc": { "$dateFromParts": {
      'year': "$dateVarFull.year",
      'month': "$dateVarFull.month",
      'day': "$dateVarFull.day"
    }}
  }}
])

结果:

{
    "dateVarFull" : {
        "year" : NumberInt(2020), 
        "month" : NumberInt(8), 
        "day" : NumberInt(27), 
        "hour" : NumberInt(13), 
        "minute" : NumberInt(0), 
        "second" : NumberInt(0), 
        "millisecond" : NumberInt(0)
    }, 
    "dateVarTrunc" : ISODate("2020-08-27T00:00:00.000+0000")
}

trunc使用iso8601: true参数:

db.getCollection("data").aggregate([
  {"$addFields": {
    "dateVarFull": {
       "$dateToParts": {
         date: {"$toDate" : "2020-08-27T13:00:00Z"},
         iso8601: true
       }
    }
  }},
  {"$addFields": {
    "dateVarTrunc": { "$dateFromParts": {
      'isoWeekYear': "$dateVarFull.isoWeekYear",
      'isoWeek': "$dateVarFull.isoWeek",
      'isoDayOfWeek': 1
    }}
  }}
])

结果:

{
    "dateVarFull" : {
        "isoWeekYear" : NumberInt(2020), 
        "isoWeek" : NumberInt(35), 
        "isoDayOfWeek" : NumberInt(4), 
        "hour" : NumberInt(13), 
        "minute" : NumberInt(0), 
        "second" : NumberInt(0), 
        "millisecond" : NumberInt(0)
    }, 
    "dateVarTrunc" : ISODate("2020-08-24T00:00:00.000+0000")
}
fae0ux8s

fae0ux8s2#

可以通过对日期或时间戳字段进行算术运算来获得ISO周的开始,这里周的开始是Monday(1),周的结束是Sunday(7)

db.dd.aggregate(
    [
        {
            $addFields : { 
                startOfWeek : 1, // Monday
                currentDayOfWeek : {$dayOfWeek : "$date"}, 
                daysToMinus : { $subtract : [{$dayOfWeek : "$date"} , 1] },
                startOfThisWeek : { $subtract : [ "$date", {$multiply : [{ $subtract : [{$dayOfWeek : "$date"} , 1 ] }, 24, 60, 60, 1000 ]  } ] }
            }
        }
    ]
).pretty()

文件

> db.dd.find()
{ "_id" : ObjectId("5a62e2697702c6be61d672f4"), "date" : ISODate("2018-01-20T06:32:09.157Z") }

周开始

{
    "_id" : ObjectId("5a62e2697702c6be61d672f4"),
    "date" : ISODate("2018-01-20T06:32:09.157Z"),
    "startOfWeek" : 1,
    "currentDayOfWeek" : 7,
    "daysToMinus" : 6,
    "startOfThisWeek" : ISODate("2018-01-14T06:32:09.157Z")
}
>
nhjlsmyf

nhjlsmyf3#

可以使用$dateFromParts函数将日期截断为iso周:
举个例子

db.dd.aggregate(
  {
    $dateFromParts: {
      isoWeekYear: { $isoWeekYear: "$date" },
      isoWeek: { $isoWeek: "$date" }
    }
  }
)

对于Fri, 22 Jun 2018 20:46:50 UTC +00:00,它返回Fri, 18 Jun 2018 00:00:00 UTC +00:00
要将日期截断为小时、日、月等,使用$dateFromString$dateToString更容易。下面的示例将日期截断为小时:

db.dd.aggregate(
  {
    $dateFromString: {
      dateString: { 
        $dateToString: {
          format: '%Y-%m-%dT%H:00:00+00:00',
          date: '$date'
        }
      }
    }
  }
)
ldioqlga

ldioqlga4#

Mongo 5开始,您的愿望已通过$dateTrunc运算符实现。
例如,将日期截断为年份:

// { date: ISODate("2021-12-05T13:20:56Z") }
// { date: ISODate("2019-04-27T05:00:32Z") }
db.collection.aggregate([
  { $project: { year: { $dateTrunc: { date: "$date", unit: "year" } } } }
])
// { year: ISODate("2021-01-01T00:00:00Z") }
// { year: ISODate("2019-01-01T00:00:00Z") }

您可以使用unit参数在不同级别的单位(年、月、日、小时...甚至季度)进行截断。对于给定的单位,可以使用binSize参数在不同的单位倍数(例如3年、6个月...)进行截断。
您还可以指定周的开始日期:

// { date: ISODate("2021-12-05T13:20:56Z") } <= Sunday
// { date: ISODate("2021-12-06T05:00:32Z") } <= Monday
db.collection.aggregate([
  { $project: {
    week: { $dateTrunc: { date: "$date", unit: "week", startOfWeek: "monday" } }
  }}
])
// { week: ISODate("2021-11-29T00:00:00Z") }
// { week: ISODate("2021-12-06T00:00:00Z") }

相关问题