在MongoDB $ project子句中,如何将日期从毫秒转换为ISODate对象

在MongoDB $ project子句中,如何将日期从毫秒转换为ISODate对象

问题描述:

我正在尝试按小时汇总MongoDB中的记录,需要将存储为时间戳(毫秒)的日期转换为ISODate,以便我可以使用聚合框架的内置日期运算符($ hour,$ month等)

I am trying to aggregate records in a MongoDB colloection by hour and need to convert date stored as timestamp (milliseconds) to ISODate so that I can use aggregate framework's built-in date operators ($hour, $month, etc.)

记录存储为

{ 
"data" : { "UserId" : "abc", "ProjId" : "xyz"}, 
"time" : NumberLong("1395140780706"),
"_id" : ObjectId("532828ac338ed9c33aa8eca7") 
} 

我正在尝试使用以下类型的聚合查询:

I am trying to use an aggregate query of following type:

db.events.aggregate(
    { 
       $match : { 
         "time" : { $gte : 1395186209804, $lte : 1395192902825 } 
       } 
    }, 
    { 
       $project : {
         _id : "$_id", 
         dt : {$concat : (Date("$time")).toString()} // need to project as ISODate
       } 
    },
    // process records further in $project or $group clause
)

产生以下形式的结果:

{
    "result" : [
        { 
            "_id" : ObjectId("5328da21fd207d9c3567d3ec"), 
            "dt" : "Fri Mar 21 2014 17:35:46 GMT-0400 (EDT)" 
        }, 
        { 
            "_id" : ObjectId("5328da21fd207d9c3567d3ed"), 
            "dt" : "Fri Mar 21 2014 17:35:46 GMT-0400 (EDT)" 
        }, 
            ... 
} 

我想提取小时,日期,月份和年份,但由于时间预测为字符串,我无法使用聚合框架的内置日期运算符($ hour等)。

I want to extract hour, day, month, and year from the date but since time is projected forward as string I am unable to use aggregate framework's built-in date operators ($hour, etc.).

如何将时间从毫秒到ISO日期转换为以下时间:

How can I convert time from milliseconds to ISO date to do sometime like the following:

db.events.aggregate(
    {
        $match : { 
            "time" : { $gte : 1395186209804, $lte : 1395192902825 } 
        }
    },
    {
        $project : {
            _id : "$_id",
            dt : <ISO date from "$time">
        }
    },
    { 
        $project : {
            _id : "$_id",
            date : { 
                hour : {$hour : "$dt"} 
            }
        }
    }
)


我假设没办法。因为聚合框架是用本机代码编写的。不使用V8引擎。因此,JavaScript的所有内容都不会在框架内运行(这也是聚合框架运行得更快的原因)。

Map / Reduce是一种工作方式,但是聚合框架肯定会有更好的性能。

I assume there's no way to do it. Because aggregation framework is written in native code. not making use of the V8 engine. Thus everything of JavaScript is not gonna work within the framework (And that's also why aggregation framework runs much faster).
Map/Reduce is a way to work this out, but aggregation framework definitely got much better performance.

关于地图/降低效能,请阅读这个线程

About Map/Reduce performance, read this thread.

另一种工作方式是从聚合框架获取原始结果,将其放入JSON数组中。然后通过运行JavaScript进行转换。分类如下:

Another way to work it out would be get a "raw" result from aggregation framework, put it into an JSON array. Then do the conversion by running JavaScript. Sort of like:

var results = db.events.aggregate(...);
reasult.forEach(function(data) {
    data.date = new Date(data.dateInMillionSeconds);
    // date is now stored in the "date" property
}