集約フレームワークを使用する必要があります。集計は次のようになります。
db.stack.aggregate([
{ $match: { "samples.key" : "test-key" } },
{ $unwind : "$samples" },
{ $match : { "samples.key" : "test-key" } },
{ $project : { "new_key" : "$samples.key", "new_value" : "$samples.value" } },
{ $group : { `_id` : "$new_key", answer : { $avg : "$new_value" } } }
])
集約フレームワークは、組み立てラインのようなものと考えるのが一番です。クエリ自体は JSON ドキュメントの配列であり、各サブドキュメントはアセンブリの異なるステップを表します。
ステップ 1: $match
最初のステップは、SQL の WHERE 句のような基本的なフィルターです。このステップを最初に配置して、 を含む配列要素を含まないすべてのドキュメントを除外しますtest-key
。これをパイプラインの先頭に配置すると、集計でインデックスを使用できるようになります。
ステップ 2: $unwind
2 番目のステップ は$unwind
、"samples" 配列内の各要素を分離するために使用されるため、それらすべてに対して操作を実行できます。そのステップだけでクエリを実行すると、私の言いたいことがわかるでしょう。簡単に言えば:
{ name : "bob",
children : [ {"name" : mary}, { "name" : "sue" } ]
}
2 つのドキュメントになります:
{ name : "bob", children : [ { "name" : mary } ] }
{ name : "bob", children : [ { "name" : sue } ] }
ステップ 3: $match
3 番目のステップ$match
は、最初の段階とまったく同じですが$match
、目的が異なります。に続くため$unwind
、この段階では、フィルター条件に一致しない以前の配列要素 (現在はドキュメント) を除外します。この場合、私たちは文書のみを保持しますsamples.key = "test-key"
ステップ 4: $project (オプション)
4 番目のステップ では$project
、ドキュメントを再構築します。この場合、項目を配列から取り出して、直接参照できるようにしました。上記の例を使用すると..
{ name : "bob", children : [ { "name" : mary } ] }
になる
{ new_name : "bob", new_child_name : mary }
この手順は完全にオプションであることに注意してください。$project
いくつかの小さな変更の後、これがなくても後の段階を完了することができます。ほとんどの場合$project
、完全に表面的なものです。集計には内部で多数の最適化が行われているため、手動でフィールドを含めたり除外したりする$project
必要はありません。
ステップ 5: $group
最後に$group
、魔法が起こる場所です。SQLの_id
世界で「グループ化」する値。2 番目のフィールドは、$project
ステップで定義した値の平均を示しています。$sum
合計を実行するために簡単に置き換えることができますが、通常、カウント操作は次の方法で行われますmy_count : { $sum : 1 }
。
ここで注意すべき最も重要なことは、行われている作業の大部分は、操作が簡単に実行できるようにデータをフォーマットすることであるということです。
ファイナルノート
最後に、これは、算術演算で使用できないテキストとして定義されているため、提供されているサンプル データでは機能しないことに注意してください。samples.value
興味がある場合は、フィールドのタイプを変更する方法について、MongoDB How to change the type of a fieldで説明しています。