按mongodb中的时间戳日期汇总数据

时间:2014-04-17 14:58:07

标签: mongodb timestamp aggregation-framework

我以unix时间戳格式存储项目的创建时间。例如,根据年份,现在我想汇总它。但是,不幸的是,它不起作用,应该...... [/ p>

这是源数据:

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。如果我在日期函数中指出准确的时间:

db.invoice.aggregate(
{$match: {id: '01f96c0d4254cdd69692d97c3909fb6dff75066b'}}, 
{$group: 
    {_id: {  year: {$year: new Date(1397661552000)}  }, 
    total: {$sum: '$amount'}}
}
)

它似乎工作并输出2014年

1 个答案:

答案 0 :(得分:3)

$year运算符和所有date aggregation运算符完全按照设计工作。但问题在于你的"创造了"实际上并不是BSON date type,实际上只是一个代表纪元时间戳的数字。

所以如果你真的有一个BSON date,它在shell中看起来像这样:

ISODate("2014-04-18T03:54:40.023Z")

然后操作员将工作。但在你的情况下他们没有,这是一种耻辱,因为BSON日期类型实际上只是一个内部的纪元时间戳,因此不会占用任何额外的存储空间。

但是因为你的"时间戳"只是数字,你需要做的只是一个小小的日期数学"为了获得你想要的年份边界:

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 converter这样的网站上查看结果中的纪元日期,或者只是将其提供给日期对象。