来自今天的MongoDB聚合记录

时间:2014-09-05 18:06:07

标签: python mongodb aggregation-framework mongoengine

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

相关的代码段是:

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
        }},
...

这是对的吗?

1 个答案:

答案 0 :(得分:2)

为了获取当天的记录,您仍然基本上需要传递一个日期范围,表示当天的开始和要查找的范围的结束。假设您已在类中使用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值的任何聚合键实际上都是当天汇总的。

如果改为“timestamp”,你实际上有一个数字代表自纪元以来的秒数(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 datetime对象中通常可用的微秒。有点不幸的是,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日期类型,因为这是最佳支持表单。