【问题标题】:pymongo group by datetimepymongo 按日期时间分组
【发布时间】:2014-03-28 17:14:18
【问题描述】:

我正在尝试按日期字段(即日期时间)搜索集合和分组记录。 我知道 pymongo 在后台将它们转换为正确的类型(ISODate 或类似的东西)。

问题是,由于 datetime 对象具有日期、时间、时区.. 我如何告诉组操作员只使用日期部分?因为否则我无法获得所需的分组,因为时间会阻止将同一天、同一月、同一年的记录组合在一起。

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

结果:

{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}]}

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

  • 仅按日期分组
  • 按日期和小时分组
  • 按日期、小时和分钟分组

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

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

或者也许有另一种方法来处理这个问题,有什么想法吗? 谢谢。

【问题讨论】:

    标签: python mongodb mongodb-query aggregation-framework pymongo


    【解决方案1】:

    是的。您可以将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 }}
    ])
    

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

    "day": { 
        "year": {"$year": "$date" },
       "month": {"$month": "$date"}, 
       "day": {"$dayOfYear": "$date"}
    }
    

    这同样有效。但这给了你一个很好的字符串。这利用了$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 } }
    ])
    

    这里datetime.datetime.utcfromtimestamp(0) 将作为代表“纪元”的 BSON 日期输入管道。当您 $subtract 一个 BSON 日期与另一个日期时,返回以毫秒为单位的差异。这使您可以通过再次减去 $mod 结果来将日期“四舍五入”到当天,以获得与一天的毫秒差的剩余部分。

    $add 也是如此,其中将 BSON 日期“添加”到数值将生成 BSON 日期。

    【讨论】:

    • 谢谢!效果很好(我已经修复了 $substr 上的括号)
    猜你喜欢
    • 2017-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2015-09-08
    • 1970-01-01
    • 2017-08-19
    相关资源
    最近更新 更多