我正在寻找这个,但我找不到任何有用的解决我的情况.我想要的是在聚合期间以几秒为单位获取MongoDB ISODate的unix时间戳.问题是我可以从ISODate中获取时间戳,但它是以毫秒为单位.所以我需要减少那些毫秒.我试过的是:
> db.data.aggregate([ {$match: {dt:2}},{$project: {timestamp: {$concat: [{$substr: ["$md",-1]},'01',{$substr: ["$id",-1]}]}}} ])
正如您所看到的,我正在尝试从’md’var中获取时间戳,并将此时间戳与’01’和’id’数字连接起来.上面的代码给出:
{ "_id" : ObjectId("52f8fc693890fc270d8b456b"),"timestamp" : "2014-02-10T16:20:56011141" }
然后我改进了命令:
> db.data.aggregate([ {$match: {dt:2}},{$project: {timestamp: {$concat: [{$substr: [{$subtract: ["$md",new Date('1970-01-01')]},-1]}]}}} ])
现在我得到:
{ "_id" : ObjectId("52f8fc693890fc270d8b456b"),"timestamp" : "1392049256000011141" }
我真正需要的是1392049256011141所以没有3额外的000.我试过$减法:
> db.data.aggregate([ {$match: {dt:2}},{$project: {timestamp: {$concat: [{$substr: [{$divide: [{$subtract: ["$md",1000]},-1]}]}}} ])
我得到的是:
{ "_id" : ObjectId("52f8fc693890fc270d8b456b"),"timestamp" : "1.39205e+009011141" }
不完全是我对命令的期望.不幸的是,$substr运算符不允许负长度.有没有人有其他解决方案?
我不确定为什么你认为你需要以秒为单位而不是毫秒的值,因为通常两种形式都是有效的,并且在大多数语言实现中,毫秒实际上是首选.但一般来说,尝试将其强制为字符串是错误的解决方法,通常你只是做数学:
db.data.aggregate([ { "$project": { "timestamp": { "$subtract": [ { "$divide": [ { "$subtract": [ "$md",new Date("1970-01-01") ] },1000 ]},{ "$mod": [ { "$divide": [ { "$subtract": [ "$md",1000 ]},1 ]} ] } }} ])
这将返回一个纪元时间戳,以秒为单位.基本上从一个BSON日期对象从另一个BSON日期对象中减去时得到的结果是以毫秒为单位的时间间隔.使用“1970-01-01”的初始纪元日期导致基本上从当前日期值中提取毫秒值. $divide
运算符基本上取消毫秒部分,$mod
执行模数以实现舍入.
实际上,您最好为您的应用程序使用本机语言进行工作,因为所有BSON日期都将作为本机“日期/日期时间”类型返回,您可以在其中提取时间戳值.考虑shell中的JavaScript基础知识:
var date = new Date() ( date.valueOf() / 1000 ) - ( ( date.valueOf() / 1000 ) % 1 )
通常使用聚合,您希望对时间戳值执行此类“数学运算”,以便在诸如一天等时间段内聚合值.聚合框架可以使用日期运算符,但您也可以使用日期数学方式:
db.data.aggregate([ { "$group": { "_id": { "$subtract": [ { "$subtract": [ "$md",{ "$mod": [ { "$subtract": [ "$md",1000 * 60 * 60 * 24 ]} ] },"count": { "$sum": 1 } }} ])
这种形式更典型的是将时间戳舍入到一天,并在这些间隔内汇总结果.
因此,仅仅提取时间戳的聚合框架的目的似乎并不是最佳用法,或者实际上不需要将其转换为秒而不是毫秒.在您的应用程序代码中,我认为您应该这样做,除非您当然希望结果的时间间隔可以应用所示的日期数学.