【问题标题】:MongoDB Aggregate Records from TodayMongoDB 从今天开始聚合记录
【发布时间】:2014-09-05 18:06:07
【问题描述】:

我正在使用 MongoDB 聚合框架来聚合记录集合。

相关代码sn-p为:

Record._get_collection().aggregate([
        { "$match": {
            "system_id": system.id
        }},
...

如何将其转换为仅限今天的汇总记录?

Record 文档有一个 utc_timestamp 字段,所以我认为它类似于:

Record._get_collection().aggregate([
        { "$match": {
            "system_id": system.id,
            { "$dayOfMonth": "$utc_timestamp" }: 5
        }},
...

这对吗?

【问题讨论】:

  • utc_timestamp 字段的格式是什么?

标签: python mongodb aggregation-framework mongoengine


【解决方案1】:

为了仅获取当天的记录,您基本上仍然需要传入一个日期范围,该日期范围表示一天的开始和要查找的范围的结束。假设您已经在您的类中使用 DateTimeField 实现了这一点,那么 MongoDB 将使用与日期聚合运算符兼容的 BSON date 类型:

Record._get_collection().Aggregate([
   { "$match": {
       "system_id": system.id,
       "utc_timestamp": { 
           "$gte": datetime.datetime(2014,9,6)
           "$lt": datetime.datetime(2014,9,7)
       }
   }},
   { "$group": {
        "_id": { "$dayOfYear": "$utc_timestamp" }
         ....

$group 级别,这些运算符通常在聚合超过一天或一天​​中的小时或分钟的更广泛范围内的值时最有意义。否则,由于已经选择了日期,因此所有内容都是当天,并且其他字段或 Null 值的任何聚合键本质上都是当天的聚合。

如果改为使用“时间戳”,您实际上有一个数字表示自纪元以来的秒数(BSON 类型实际上在内部使用自纪元以来的毫秒数),那么您可以像这样构造查询:

Record._get_collection().Aggregate([
   { "$match": {
       "system_id": system.id,
       "utc_timestamp": { 
           "$gte": ( datetime.datetime(2014,9,6)
                  - datetime.datetime(1970,1,1)).total_seconds()
           "$lt": ( datetime.datetime(2014,9,7) 
                  - datetime.datetime(1970,1,1)).total_seconds()
       }
   }},
   { "$group": {
        "_id": { 
           "$subtract": [
              "$utc_timestamp",
              { "$mod": [
                  "$utc_timestamp",
                  60 * 60 * 24
              ]}
           ]
        },
        ...

或者类似地调整毫秒,这是一种更常见的纪元时间戳格式,乘以 1000。对于分组标准“日期数学”,通过将匹配的时间戳值四舍五入到当天来应用。

最后,MongoEngine 支持ComplexDateTimeField,它可以保持通常在 python 日期时间对象中可用的微秒。不幸的是,在这种情况下,MongoDB 中的实际存储是一个“字符串”,因此数学或通用日期运算符都不是真正可用的。但是该字符串的格式为YYYY,MM,DD,HH,MM,SS,NNNNNN,它至少是“词法”排序的,因此可以使用$substr 进行范围选择和剖析,以便聚合到一天或其他时间段:

Record._get_collection().Aggregate([
   { "$match": {
       "system_id": system.id,
       "utc_timestamp": { 
           "$gte": "2014,09,06", "$lt": "2014,09,07"
       }
   }},
   { "$group": {
       "_id": { "$substr": [ "$utc_timestamp", 0, 10 ] }
       ...

但是,如果您使用任何其他形式的字符串,那么您将遇到问题,因为它不太可能很好地转换为查询匹配或分组键选择。在这种情况下,您最好将任何此类字符串转换为使用上述形式之一,明显偏好使用本机 BSON 日期类型,因为这是最受支持的形式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 1970-01-01
    相关资源
    最近更新 更多