MongoDB Aggregate -按月对时间戳字段(int)进行分组



我无法在字段上按月分组,值为时间戳。

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

让我们从$month支持哪些类型的输入开始:

日期、时间戳或ObjectID。

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

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

如果您使用的是较早的Mongo版本,并且无法访问此函数,您可以使用"hacky"使用$add进行聚合,当它获得一个数字和一个日期类型时,它将返回一个日期类型。

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

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

您可以先转换"created_at"使用"addFields"阶段,

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

最新更新