web-dev-qa-db-ja.com

日付をミリ秒からISODateオブジェクトに変換します

MongoDBコレクションのレコードを1時間ごとに集計しようとしています。集計フレームワークの組み込み日付演算子($ hour、$ monthなど)を使用できるように、タイムスタンプ(ミリ秒)として保存された日付をISODateに変換する必要があります。

レコードは次のように保存されます

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

次のタイプの集計クエリを使用しようとしています。

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など)を使用できません。

次のような場合に、時間をミリ秒から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"} 
            }
        }
    }
)
21
Sid Thakur

私はそれをする方法がないと思います。集約フレームワークはネイティブコードで記述されているためです。 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
}
7
yaoxing

実際には、次のような構文を使用して、ミリ秒の時間をゼロミリ秒のDate()オブジェクトに追加するのがコツです。

dt : {$add: [new Date(0), "$time"]}

結果を生成するために、上から集計を変更しました。

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

結果は次のとおりです(サンプルデータのエントリが1つあります)。

{
  "result": [
    {
      "_id": ObjectId("532828ac338ed9c33aa8eca7"),
      "date": {
        "hour": 11
      }
    }
  ],
  "ok": 1
}
31
Astral

有効なBSON日付を返すために必要なのは、 _$add_ 演算子を使用した小さな日付「数学」だけです。タイムスタンプにnew Date(0)を追加する必要があります。 new Date(0)は、Unixエポック(1970年1月1日)からのミリ秒数を表し、new Date("1970-01-01")の省略形です。

_db.events.aggregate([
    { "$match": { "time": { "$gte" : 1395136209804, "$lte" : 1395192902825 } } },
    { "$project": { 
        "hour": { "$hour": { "$add": [ new Date(0), "$time" ] } }, 
        "day": { "$dayOfMonth":  { "$add": [ new Date(0), "$time" ] } },
        "month": { "$month": { "$add": [ new Date(0), "$time" ] } },
        "year": { "$year":  { "$add": [ new Date(0), "$time" ] } } 
    }} 
])
_

収量:

_{
    "_id" : ObjectId("532828ac338ed9c33aa8eca7"),
    "hour" : 11,
    "day" : 18,
    "month" : 3,
    "year" : 2014
}
_
2
styvane

開始Mongo 4.0、新しい $toDate さまざまなタイプから日付に変換できる集約演算子(この場合はlongから):

// { time: NumberLong("1395140780706") }
db.collection.aggregate({ $set: { time: { $toDate: "$time" } } })
// { time: ISODate("2014-03-18T11:06:20.706Z") }

そしてそれから時間を得るために:

// { time: NumberLong("1395140780706") }
db.collection.aggregate({ $project: { hour: { $hour: { $toDate: "$time" } } } })
// { hour: 11 }
1
Xavier Guihot

{$add: [new Date(0), "$time"]}関数がstring typeではなくISO date typeを返す場合にこれを使用します

私はそのオプションをすべて使用しますが、それでも失敗します。$projectからの新しい日付は、ISO('2000-11-2:xxxxxxx')のようなstring typeではなく'2000-11-2:xxxxxxx'のようなdate typeを返すため、これを使用します。

db.events.aggregate(
    {
        $project : {
            _id : "$_id",
            dt : {$add: [new Date(0), "$time"]}
        }
    },
    { 
        $project : {
            _id : "$_id",
            "year": { $substr: [ "$dt", 0, 4 ] },
            "month": { $substr: [ "$dt", 5, 2] },
            "day": { $substr: [ "$dt", 8, 2 ] }
        }
    }
);

結果は次のようになります

 { _id: '59f940eaea87453b30f42cf5',
    year: '2017',
    month: '07',
    day: '04' 
},

stringsubsetに応じて、必要に応じて時間または分を取得できます。同じ日付、月、または年に応じてgroup

0
KEKUATAN