前述のように、次のようなすべてのキーを実際に提供する場合を除いて、集約フレームワークではこのようなドキュメントの処理はできません。
db.events.aggregate([
{ "$group": {
"_id": "$app_id",
"event_count": { "$sum": "$event_count" },
"0": { "$sum": "$event_count_per_type.0" },
"10": { "$sum": "$event_count_per_type.10" }
"20": { "$sum": "$event_count_per_type.20" }
"30": { "$sum": "$event_count_per_type.30" }
}}
])
ただし、もちろん、すべてを明示的に指定する必要があります 作業したいキー。これは、MongoDBの集計フレームワークと一般的なクエリ操作の両方に当てはまります。この「サブドキュメント」フォームで表記された要素にアクセスするには、要素を操作するために要素への「正確なパス」を指定する必要があります。
集計フレームワークと一般的なクエリには「トラバーサル」の概念がありません。つまり、ドキュメントの「各キー」を処理できません。そのためには、これらのインターフェースでは提供されていない言語構成が必要です。
ただし、一般的に言えば、名前が実際に「値」を表すデータポイントとして「キー名」を使用することは、少し「アンチパターン」です。これをモデル化するためのより良い方法は、配列を使用して、「タイプ」をそれ自体で値として表すことです。
{
"app_id": "DHJFK67JDSJjdasj909",
"date: ISODate("2014-08-07T00:00:00.000Z"),
"event_count": 32423,
"events": [
{ "type": 0, "value": 322 },
{ "type": 10, "value": 4234 },
{ "type": 20, "value": 653 },
{ "type": 30, "value": 7562 }
]
}
また、「日付」が文字列ではなく適切な日付オブジェクトになったことにも注意してください。これも実行するのに適した方法です。ただし、この種のデータは、集計フレームワークを使用して簡単に処理できます。
db.events.aggregate([
{ "$unwind": "$events" },
{ "$group": {
"_id": {
"app_id": "$app_id",
"type": "$events.type"
},
"event_count": { "$sum": "$event_count" },
"value": { "$sum": "$value" }
}},
{ "$group": {
"_id": "$_id.app_id",
"event_count": { "$sum": "$event_count" },
"events": { "$push": { "type": "$_id.type", "value": "$value" } }
}}
])
これは、最初に各「キー」を指定せずに「タイプ」ごとの合計を取得する2段階のグループ化を示しています。次に、「app_id」ごとに1つのドキュメントとして返され、結果は元々保存されていた配列になります。このデータフォームは、通常、特定の「タイプ」または特定の範囲内の「値」を表示するための柔軟性がはるかに高くなっています。
構造を変更できない場合、唯一のオプションはmapReduceです。これにより、キーのトラバーサルを「コーディング」できますが、JavaScriptの解釈と実行が必要なため、集約フレームワークほど高速ではありません。
db.events.mapReduce(
function() {
emit(
this.app_id,
{
"event_count": this.event_count,
"event_count_per_type": this.event_count_per_type
}
);
},
function(key,values) {
var reduced = { "event_count": 0, "event_count_per_type": {} };
values.forEach(function(value) {
for ( var k in value.event_count_per_type ) {
if ( !redcuced.event_count_per_type.hasOwnProperty(k) )
reduced.event_count_per_type[k] = 0;
reduced.event_count_per_type += value.event_count_per_type;
}
reduced.event_count += value.event_count;
})
},
{
"out": { "inline": 1 }
}
)
これは基本的に「キー」をトラバースして結合し、見つかった各キーの値を合計します。
したがって、オプションは次のいずれかです。
- 構造を変更し、標準のクエリと集計を使用します。
- 構造を維持し、JavaScript処理とmapReduceが必要です。
実際のニーズにもよりますが、ほとんどの場合、リストラはメリットをもたらします。