我以unix时间戳格式存储项目的创建时间。现在我想把它聚合起来,例如,根据年份。但是,不幸的是,它不起作用,应该。。。
以下是源数据:
db.invoice.find({id: '01f96c0d4254cdd69692d97c3909fb6dff75066b'}, {created: 1, amount: 1})
{ "_id" : ObjectId("534801e8e71709fab334bdd9"), "amount" : 345, "created" : 1397661552 }
但当我尝试做:
db.invoice.aggregate(
{$match: {id: '01f96c0d4254cdd69692d97c3909fb6dff75066b'}},
{$group:
{_id: { year: {$year: new Date('$created' * 1000)} },
total: {$sum: '$amount'}}
}
)
我得到
"result" : [
{
"_id" : {
"year" : 292278994
},
"total" : 345
}
],
"ok" : 1
这一年很奇怪。。。
p.s.如果我在Date函数中指出确切时间:
db.invoice.aggregate(
{$match: {id: '01f96c0d4254cdd69692d97c3909fb6dff75066b'}},
{$group:
{_id: { year: {$year: new Date(1397661552000)} },
total: {$sum: '$amount'}}
}
)
它似乎工作和输出2014年
$year
运算符和所有日期聚合运算符完全按照设计工作。但这里的问题是,您的"created"实际上不是BSON日期类型,实际上只是一个表示epoch时间戳的数字。
所以,如果你真的有一个BSON日期,它在外壳中看起来是这样的:
ISODate("2014-04-18T03:54:40.023Z")
然后操作员将工作。但在您的情况下,它们没有,这是一个遗憾,因为BSON日期类型实际上只是内部的epoch时间戳,因此不会占用任何额外的存储空间。
但由于你的"时间戳"只是数字,你所需要做的就是做一点"日期数学",以获得你想要的年份界限:
db.invoice.aggregate([
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
"$created",
{ "$mod": [
"$created",
31536000 // 60 * 60 * 24 * 365
]}
]},
950400 // correction
]
},
"total": { "$sum": "$amount" }
}}
])
这应该将每个日期值设置为一年中的第一天,这样你就可以按年份进行汇总。
"result" : [
{
"_id" : {
"year" : 1388534400
},
"total" : 345
}
],
"ok" : 1
您可以在类似epoch转换器的网站上检查结果中的epoch日期,或者只将其输入到date对象中。