この構造のような「ステータス」コレクションがあります-
{
_id: ObjectId("545a0b63b03dbcd1238b4567"),
status: 1004,
comment: "Rem dolor ipsam placeat omnis non. Aspernatur nobis qui nisi similique.",
created_at: ISODate("2014-11-05T11:34:59.804Z")
},
{
_id: ObjectId("545a0b66b03dbcd1238b4568"),
status: 1001,
comment: "Sint et eos vero ipsa voluptatem harum. Hic unde voluptatibus et blanditiis quod modi.",
created_at: ISODate("2014-11-05T11:35:02.814Z")
}
....
....
そのコレクションから15分間隔でグループ化された結果を取得する必要があります。
これを行うにはいくつかの方法があります。
1つは Date Aggregation Operators を使用して、ドキュメント内の「日付」値を分析できるようにします。具体的には、「グループ化」を主な目的としています。
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$created_at" },
"dayOfYear": { "$dayOfYear": "$created_at" },
"hour": { "$hour": "$created_at" },
"interval": {
"$subtract": [
{ "$minute": "$created_at" },
{ "$mod": [{ "$minute": "$created_at"}, 15] }
]
}
}},
"count": { "$sum": 1 }
}}
])
2番目の方法は、日付オブジェクトが別の日付オブジェクトから減算(または他の直接的な数学演算)されるときのちょっとしたトリックを使用することです。したがって、エポック日付を使用するだけで、エポックミリ秒表現を取得できます。次に、間隔に日付計算を使用します。
db.collection.aggregate([
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$created_at", new Date("1970-01-01") ] },
{ "$mod": [
{ "$subtract": [ "$created_at", new Date("1970-01-01") ] },
1000 * 60 * 15
]}
]
},
"count": { "$sum": 1 }
}}
])
したがって、グループ化間隔に必要な出力形式の種類によって異なります。どちらも基本的に同じものを表し、コード内で「日付」オブジェクトとして再構築するのに十分なデータを持っています。
グループ化_id
の後の「グループ化演算子」部分には、必要なものを何でも配置できます。私はあなたが本当にやりたいことに関するあなた自身からの実際の声明の代わりに、基本的な「カウント」の例を使用しています。
オリジナルの執筆以来、日付集計演算子にいくつかの追加がありましたが、BSON日付変換で行われる基本的な数学のトリックとは対照的に、MongoDB 4.0からは実際の「型の実際のキャスト」が行われます。
たとえば、ここで新しいヘルパーとして $toLong
および $toDate
を使用できます。
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": "$created_at" },
{ "$mod": [ { "$toLong": "$created_at" }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
これは少し短く、「エポック」値の外部BSON日付をパイプライン定義の定数として定義する必要がないため、すべての言語実装でかなり一貫しています。
これらは、型変換用の「ヘルパー」メソッドの2つにすぎず、すべて $convert
メソッドに結び付けられています。これは、null
または変換エラー。
このようなキャストでは、主キーのDate
からObjectId
情報を取得することもできます。これは、「作成」日付の信頼できるソースであるためです。
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": { "$toDate": "$_id" } },
{ "$mod": [ { "$toLong": { "$toDate": "$_id" } }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
したがって、この種の変換を使用した「キャストタイプ」は非常に強力なツールになります。
警告-
ObjectId
値は秒$toDate
変換を許可するデータの一部を構成する内部時間値に対してのみ。実際に挿入される「時間」は、おそらく使用中のドライバーに依存します。 precisionが必要な場合、ObjectId
値に依存する代わりに、個別のBSON Dateフィールドを使用することをお勧めします。
私はここで他の答えが好きで、主に集計日付演算子の代わりに日付数学を使用するのが好きです。
ここで追加したいのは、結果として「数値」タイムスタンプではなく、このアプローチによって集約フレームワークからDate
オブジェクトを返すこともできることです。 _$add
_ を使用して、同じ原理に基づいた少し余分な計算を行います。
_db.collection.aggregate([
{ "$group": {
"_id": {
"$add": [
{ "$subtract": [
{ "$subtract": [ "$current_date", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$current_date", new Date(0) ] },
1000 * 60 * 15
]}
] },
new Date(0)
]
},
"count": { "$sum": 1 }
}}
])
_
JavaScriptのDate(0)
構文は、エポックからの0ミリ秒がエポックであるため、同じ「エポック」日付を短い形式で表します。しかし、主なポイントは、別のBSON日付オブジェクトへの「追加」が数値識別子で行われた場合、記述された条件の逆が真になり、最終結果は実際にはDate
になるということです。
すべてのドライバーは、このアプローチによってネイティブのDate
型をそれぞれの言語に返します。
Mongodb.version()<3.0のもう少し美しい
db.collection.aggregate([
{$match: {created_at:{$exists:1}}},
{$group: {
_id: {$add:[
{$dayOfYear: "$created_at" },
{$multiply: [{$year: "$created_at"}, 1000]}
]},
count: {$sum: 1 }
}},
{$sort:{_id:-1}}
])
別の便利な方法:
db.collection.aggregate([
{$group: {
_id: {
overallTime: {
$dateToString: { format: "%Y-%m-%dT%H", date: "$created_at" }
},
interval: { $trunc: { $divide: [{ $minute: "$created_at" }, 15 ]}}
},
}},
])
min、hour、day間隔の方が簡単です:
var format = "%Y-%m-%dT%H:%M"; // 1 min
var format = "%Y-%m-%dT%H"; // 1 hour
var format = "%Y-%m-%d"; // 1 day
db.collection.aggregate([
{$group: {
_id: { $dateToString: { format: format, date: "$created_at" } },
}},
])
https://stackoverflow.com/a/26814496/8474325 での@Neil Lunnの答えは、MongoDb 4.x上向きの場合は素晴らしいです。しかし、彼が集計にObjectIdを使用するコードには小さな間違いがあります。コードを機能させるには、行{ "$toDate": "_id" }
を{ "$toDate": "$_id" }
に変更する必要があります。
これが修正されたコードです。
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": { "$toDate": "$_id" } },
{ "$mod": [ { "$toLong": { "$toDate": "$_id" } }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])