MongoDBの集計パイプラインでネストされたフィールドを配列のカウント値ごとにグループ化する方法
MongoDBの集計パイプライン(Aggregation Framework)では、ネストされたオブジェクト内の複数のキーをそれぞれグループ化し、対応する値を合計したいケースがよくあります。この記事では、$objectToArray・$unwind・$groupの3つの演算子を組み合わせて、ネストされたフィールドを配列内のカウント値でグループ化する具体的な手順を紹介します。
サンプルコレクションの作成
まず、insertOne()メソッドを使って、ネストされたドキュメントを持つコレクションを作成します。「Details」オブジェクトの中には「X」と「Y」の2つのキーがあり、それぞれが「Values」(数値の配列)と「Number」(配列の要素数)を持つ構造になっています。
> db.demo99.insertOne({
... 'Details': {
... 'X': {
... 'Values': [10, 30, 50],
... 'Number': 3
... },
... 'Y': {
... 'Values': [1000, 180],
... 'Number': 2
... }
... }
... });
{
"acknowledged": true,
"insertedId": ObjectId("5e2d91eab8903cdd865577b9")
}
> db.demo99.insertOne({
... 'Details': {
... 'X': {
... 'Values': [100, 300, 500, 6000],
... 'Number': 4
... },
... 'Y': {
... 'Values': [10, 20, 60],
... 'Number': 3
... }
... }
... });
{
"acknowledged": true,
"insertedId": ObjectId("5e2d927bb8903cdd865577ba")
}
登録したドキュメントの確認
find()メソッドを実行して、コレクション内のすべてのドキュメントを表示してみましょう。
> db.demo99.find();
上記のクエリを実行すると、次のような出力が得られます。
{ "_id" : ObjectId("5e2d91eab8903cdd865577b9"), "Details" : { "X" : { "Values" : [ 10, 30, 50 ], "Number" : 3 }, "Y" : { "Values" : [ 1000, 180 ], "Number" : 2 } } }
{ "_id" : ObjectId("5e2d927bb8903cdd865577ba"), "Details" : { "X" : { "Values" : [ 100, 300, 500, 6000 ], "Number" : 4 }, "Y" : { "Values" : [ 10, 20, 60 ], "Number" : 3 } } }
ネストされたフィールドをカウント値でグループ化する集計クエリ
続いて、配列内のカウント値をもとに、ネストされたフィールドをグループ化するための集計クエリを見ていきましょう。
> db.demo99.aggregate([
... { $project: { Count: { $objectToArray: "$Details" } } },
... { $unwind: "$Count" },
... { $group: { _id: "$Count.k", count: { $sum: "$Count.v.Number" } } }
... ])
このクエリを実行すると、次の出力が返されます。
{ "_id" : "Y", "count" : 5 }
{ "_id" : "X", "count" : 7 }
クエリの動作のポイント
各ステージがどのように機能しているのかを簡単に整理します。
- $project + $objectToArray:「Details」オブジェクトを、
k(キー名)とv(値)のペアからなる配列へ変換します。これにより、事前にキー名が分からない動的な構造でも扱えるようになります。 - $unwind:変換後の配列を展開し、キーごとに個別のドキュメントとして扱えるようにします。
- $group:
$Count.k(つまり「X」「Y」などのキー名)でグループ化し、$sum演算子を使って各キーに紐づく「Number」の値を合計します。
その結果、キー「X」の合計は 3 + 4 = 7、キー「Y」の合計は 2 + 3 = 5 となり、期待どおりの集計結果が得られます。このテクニックは、キー名が固定されていない柔軟なドキュメント構造を集計したい場合に特に役立ちます。
-
MongoDBで配列フィールドに対して$allを使って全要素に一致させる方法
配列フィールドの全要素に一致させるには MongoDBで配列内のすべての指定要素を含むドキュメントを検索したい場合には、$all 演算子を使用します。$all は、対象フィールドの値が配列であり、その配列が指定した要素をすべて含んでいるドキュメントだけを選択するクエリ演算子です。 ここでは、サンプルコレクションを作成し、実際に $all を使った検索手順を順番に見ていきましょう。 1. コレクションへのドキュメント登録 まずは insertOne() メソッドを使って、サンプルコレクション「demo695」にドキュメントを挿入します。 > db.demo695.insertOne({L
-
MongoDBの集計パイプラインで複数フィールドをカウントする方法($facet活用)
MongoDBで複数のフィールドごとにドキュメントをカウントしたい場合、$facet演算子を使うのが効果的です。$facetは、同じ入力ドキュメント群に対して、単一のステージ内で複数の集計パイプラインを同時に処理できる強力な機能です。この記事では、実際にコレクションを作成し、$facetを組み合わせた集計クエリで複数フィールドの値をカウントする手順を解説します。1. サンプルコレクションの作成まず、insertOne()メソッドを使ってサンプルドキュメントを挿入します。各ドキュメントにはdetails1・details2・details3という3つのネストされたフィールドを持たせます。>