【问题标题】:MongoDB Aggregate - Group by month on a field with timestamp(int)MongoDB Aggregate - 按月对带有时间戳(int)的字段进行分组
【发布时间】:2021-02-12 09:00:11
【问题描述】:

我无法聚合一个按月分组的集合,字段值为时间戳。

Collection(Dummy):
{
   "created_at": 1232341243
}, {...}, ...

现在,如果我想在一个月内使用 $month 聚合此集合的文档,则会引发以下错误:

db.getCollection('dummy').aggregate([{"$group": {"_id": {"$month": "$created_at"}}}])

Error message
"errmsg" : "can't convert from BSON type int to Date",

MongoDB 版本:3.6.3

【问题讨论】:

    标签: python-3.x mongodb aggregate


    【解决方案1】:

    我们先来看看$month支持哪些类型的输入:

    日期、时间戳或 ObjectID。

    因此,对于 Mongo 4.0+ 版本,您可以使用 $toDate 将有效(数字)ts 或有效日期字符串转换为 Date 对象,如下所示:

    {"$group": {"_id": {"$month": {"$toDate":"$created_at"}}}}
    

    由于您使用的是早期的 Mongo 版本并且无权访问此功能您可以使用 $add 使用“hacky”聚合,因为当它获取数字和日期类型时,它将返回日期类型。

    唯一需要注意的是,您需要将时间戳(以从 epoch 0 开始的秒数表示)转换为毫秒。即乘以 1000,如下所示:

    from datetime import datetime
    
    ...
    
    {
        "$group": {
            "_id": {
                "$month": {
                    '$add': [
                        datetime(1970, 1, 1),
                        {'$multiply': ["$created_at", 1000]}
                    ]
                }
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以先使用“addFields”阶段将“created_at”时间戳转换为日期,

      {
      $addFields: {
          convertedDate: {"$toDate":"$created_at"}
        }
      }
      

      之后,您可以进行进一步的操作。所以最后你的聚合查询将是这样的, 对于 3.6 版

      [
        {
         '$project': {
            "convertedDate": { "$add": [ new Date(0), "$created_at" ] }
          }
        },
        {
          '$project': {
            'month': {
              '$month': '$convertedDate'
            }, 
            'year': {
              '$year': '$convertedDate'
            }
          }
        }, {
          '$group': {
            '_id': {
              'month': '$month', 
              'year': '$year'
            }, 
            'total': {
              '$sum': 1
            }, 
            'month': {
              '$first': '$month'
            }, 
            'year': {
              '$first': '$year'
            }
          }
        }
      ]
      

      对于版本 4+

      [
        {
         '$addFields': {
          'convertedDate': {"$toDate":"$created_at"}
          }
        },
        {
          '$project': {
            'month': {
              '$month': '$convertedDate'
            }, 
            'year': {
              '$year': '$convertedDate'
            }
          }
        }, {
          '$group': {
            '_id': {
              'month': '$month', 
              'year': '$year'
            }, 
            'total': {
              '$sum': 1
            }, 
            'month': {
              '$first': '$month'
            }, 
            'year': {
              '$first': '$year'
            }
          }
        }
      ]
      

      【讨论】:

      • 无法识别的表达式'$toDate',我猜它可以从 mongo 4 获得,我在 3.6
      • 对于 3.6 版,您可以将 addField Stage 替换为 {'$project:{ "convertedDate": { "$add": [ new Date(0), "$created_at" ] } }} 。您可以查看我更新的答案
      猜你喜欢
      • 2012-03-30
      • 2021-10-22
      • 2014-01-05
      • 2014-05-31
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多