pymongo group by datetime

Seb*_*ian 4 python mongodb pymongo mongodb-query aggregation-framework

我试图通过日期字段搜索集合和组记录,这是一个日期时间.我知道pymongo会在背景上将那些转换为正确的类型(ISODate或类似的东西).

问题是,因为datetime对象有日期,时间,时区..我怎么能告诉组操作员只使用日期部分?因为否则我没有得到所需的分组,因为时间阻止将同一天,月,年的记录组合在一起.

db.test.aggregate([
        {"$group": {
             "_id": "$date", 
             "count": {"$sum": 1}
        }},
        {"$limit": 10}])
Run Code Online (Sandbox Code Playgroud)

结果:

{u'ok': 1.0,
 u'result': [
  {u'_id': datetime.datetime(2014, 2, 15, 18, 49, 9, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
   u'count': 1},
  {u'_id': datetime.datetime(2014, 2, 15, 18, 36, 38, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
   u'count': 1},
  {u'_id': datetime.datetime(2014, 2, 15, 18, 23, 56, tzinfo=<bson.tz_util.FixedOffset object at 0x318f210>),
   u'count': 1}]}
Run Code Online (Sandbox Code Playgroud)

控制用于分组的日期时间信息会很好,

  • 仅按日期分组
  • 按日期和小时分组
  • 按日期,小时和分钟分组
  • 等等

是否有类似的东西:(或某种方式告诉仅使用日期)

db.test.aggregate([
          {"$group": {
              "_id": "$date.date()",
              "count": {"$sum": 1}
          }},
          {"$sort": "_id"}
])
Run Code Online (Sandbox Code Playgroud)

或者也许有另一种处理这个问题的方法,任何想法?谢谢.

Nei*_*unn 6

是.您可以将Date Operators$ substr$ concat结合使用.

db.test.aggregate([
    {"$group": {
        "_id" : { "$concat": [
            {"$substr": [{"$year": "$date"}, 0, 4 ]},
            "-",
            {"$substr": [{"$month": "$date"}, 0, 2 ]},
            "-",
            {"$substr": [{"$dayOfMonth": "$date"}, 0, 2 ]},
        ]},
        "count": {"$sum": 1 }
     }},
     {"$sort": { "_id": 1 }}
])
Run Code Online (Sandbox Code Playgroud)

您可以只使用日期运算符并生成文档,如下所示:

"day": { 
    "year": {"$year": "$date" },
   "month": {"$month": "$date"}, 
   "day": {"$dayOfYear": "$date"}
}
Run Code Online (Sandbox Code Playgroud)

这也很有效.但这会给你一个很好的字符串.这利用了$substr将从整数转换为字符串的事实.如果它被添加到文档中.

查看Date Operators文档,了解可在日期使用的其他时间段的用法.


更好的是,使用日期数学返回BSON日期:

import datetime

db.test.aggregate([
    { "$group": {
        "_id": {
            "$add": [
               { "$subtract": [
                   { "$subtract": [ "$date", datetime.datetime.utcfromtimestamp(0) ] },
                   { "$mod": [
                       { "$subtract": [ "$date", datetime.datetime.utcfromtimestamp(0) ] },
                       1000 * 60 * 60 * 24
                   ]}
               ]},
               datetime.datetime.utcfromtimestamp(0)
           ]
        },
        "count": { "$sum": 1 }
    }},
    { "$sort": { "_id": 1 } }
])
Run Code Online (Sandbox Code Playgroud)

这里datetime.datetime.utcfromtimestamp(0)将作为代表"纪元"的BSON日期送入管道.当您$subtract从另一个BSON Date开始时,将返回以毫秒为单位的差异.这允许您通过再次减去$mod结果来将日期"舍入"到当天,以获得与一天相差的剩余毫秒数.

$addBSON日期"添加"到数值的位置也会产生BSON日期.