将日期从毫秒转换为ISODate对象

Sid*_*kur 21 javascript type-conversion mongodb aggregation-framework

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

记录存储为

{ 
"data" : { "UserId" : "abc", "ProjId" : "xyz"}, 
"time" : NumberLong("1395140780706"),
"_id" : ObjectId("532828ac338ed9c33aa8eca7") 
} 
Run Code Online (Sandbox Code Playgroud)

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

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
)
Run Code Online (Sandbox Code Playgroud)

产生以下形式的结果:

{
    "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)" 
        }, 
            ... 
} 
Run Code Online (Sandbox Code Playgroud)

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

如何将时间从毫秒转换为ISO日期,以执行以下操作:

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

Ast*_*ral 31

实际上,有可能的诀窍是使用类似于以下语法的方法将您的毫秒时间添加到零毫秒Date()对象:

dt : {$add: [new Date(0), "$time"]}
Run Code Online (Sandbox Code Playgroud)

我从上面修改了你的聚合以产生结果:

db.events.aggregate(
    {
        $project : {
            _id : "$_id",
            dt : {$add: [new Date(0), "$time"]}
        }
    },
    { 
        $project : {
            _id : "$_id",
            date : { 
                hour : {$hour : "$dt"} 
            }
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

结果是(您的样本数据有一个条目):

{
  "result": [
    {
      "_id": ObjectId("532828ac338ed9c33aa8eca7"),
      "date": {
        "hour": 11
      }
    }
  ],
  "ok": 1
}
Run Code Online (Sandbox Code Playgroud)


yao*_*ing 7

我认为没有办法做到这一点.因为聚合框架是用本机代码编写的.没有使用V8引擎.因此,JavaScript的所有内容都无法在框架内工作(这也是聚合框架运行速度更快的原因).
Map/Reduce是一种解决这个问题的方法,但聚合框架肯定会有更好的性能.

关于Map/Reduce性能,请阅读此主题.

另一种解决方法是从聚合框架中获取"原始"结果,将其放入JSON数组中.然后通过运行JavaScript进行转换.有点像:

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