MongoDB
 Computer >> コンピューター >  >> プログラミング >> MongoDB

MongoDBで深くネストしたサブリストを連結する方法|aggregate()と$unwindの使い方

MongoDBで深くネストされたサブリスト(配列)を連結・展開したい場合は、aggregate()メソッド$unwind演算子を組み合わせるのが効果的です。$unwindを使うことで、配列フィールドを個別のドキュメントに分解し、フラットな構造へと変換できます。

まず、サンプル用のコレクションを作成しましょう。以下の例では、demo70というコレクションに、「first → details.second → StudentDetails.Score」という二重の配列構造を持つドキュメントを挿入しています。

> db.demo70.insertOne(
... {
...       "first" : [
...          {
...             "details" : {
...                "second" : [
...                   {
...                      "StudentDetails" : {
...                      "Score" : 10
...                   }
...               },
...              {
...                 "StudentDetails" : {
...                   "Score" : 20
...                }
...             },
...             {
...                "StudentDetails" : {
...                   "Score" : 30
...                }
...             }
...          ]
...       }
...    },
...    {
...       "details" : {
...          "second" : [
...             {
...                "StudentDetails" : {
...                "Score" : 11
...                }
...             },
...             {
...                "StudentDetails" : {
...                   "Score" : 18
...                }
...             },
...             {
...                "StudentDetails" : {
...                   "Score" : 29
...                   }
...                }
...             ]
...          }
...       }
...    ]
... }
... );
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e29ad4d0912fae76b13d76d")
}

insertOne()が正常に実行されると、acknowledged: trueとともに、挿入されたドキュメントのObjectIdが返されます。

登録データの確認

次に、find()メソッドを使ってコレクション内のすべてのドキュメントを表示し、データ構造を確認してみましょう。

> db.demo70.find().pretty();

上記のコマンドを実行すると、次のような出力が得られます。first配列の中にdetailsオブジェクトが含まれ、その中のsecond配列にさらにStudentDetails(Score値)が格納されており、深いネスト構造になっていることがわかります。

{
   "_id" : ObjectId("5e29ad4d0912fae76b13d76d"),
   "first" : [
      {
         "details" : {
            "second" : [
                  {
                     "StudentDetails" : {
                     "Score" : 10
                  }
              },
             {
                "StudentDetails" : {
                   "Score" : 20
                  }
               },
             {
                "StudentDetails" : {
                   "Score" : 30
                  }
               }
            ]
         }
      },
      {
         "details" : {
            "second" : [
               {
                  "StudentDetails" : {
                     "Score" : 11
                 }
              },
              {
               "StudentDetails" : {
                  "Score" : 18
                    }
                   },
               {
                  "StudentDetails" : {
                     "Score" : 29
                    }
                 }
            ]
         }
      }
   ]
}

サブリストを連結する集計クエリ

それでは、深いサブリストを連結(展開)するための実際のクエリを見ていきましょう。このパイプラインのポイントは以下の通りです。

  • $unwindを2回実行:first配列とfirst.details.second配列を順番に展開します
  • $sort(降順):Scoreの値で降順に並べ替えます
  • $limit:上位3件に絞り込みます
  • $replaceRoot:StudentDetailsを結果のルートに昇格させます
  • $sort(昇順):最後にScoreの昇順で整えて出力します
> db.demo70.aggregate([
... { $unwind: "$first" },
... { $unwind: "$first.details.second" },
... { $sort: { "first.details.second.StudentDetails.Score": -1 } },
... { $limit: 3 },
... { $replaceRoot: { newRoot: "$first.details.second.StudentDetails" } },
... { $sort: { "Score": 1 } }
... ]);

このクエリを実行すると、ネストされたすべてのScore値が連結・展開され、そのうち上位3件(30、29、20)が抽出されます。最終的な出力は次のようになります。

{ "Score" : 20 }
{ "Score" : 29 }
{ "Score" : 30 }

まとめ

このように、aggregate()パイプライン内で$unwindを段階的に適用すれば、どれほど深くネストした配列でもフラット化し、柔軟に並べ替えや絞り込みを行うことができます。さらに$replaceRootを組み合わせることで、必要なフィールドだけを取り出したクリーンな結果を取得できるのも大きなメリットです。複雑な階層構造のデータを扱う際は、ぜひこの手法を活用してみてください。

  1. MongoDBで埋め込みドキュメント(配列内のサブドキュメント)をクエリする方法

    MongoDBの埋め込みドキュメントをクエリするには?MongoDBでは、ドキュメントの中に配列として埋め込まれたサブドキュメントをクエリする場合、aggregate()メソッドを使用するのが効果的です。この記事では、$unwindと$matchを組み合わせて、埋め込みドキュメントから条件に合うデータを抽出する手順を解説します。1. サンプルコレクションの作成まずは、学生情報を配列として持つドキュメントを含むコレクションを作成しましょう。insertOne()メソッドを使ってドキュメントを挿入します。> db.demo705.insertOne( ... { ...

  2. MongoDBで条件付きの文字列連結を行う方法($condと$concatの使い方)

    MongoDBで条件付きの文字列連結を実現する方法 MongoDBでは、$cond演算子の中で$concatを組み合わせることで、条件に基づいた文字列の連結とドキュメントのフィルタリングが可能です。本記事では、実際のコード例を通じて、その実装手順をわかりやすく解説します。 サンプルコレクションの作成 まず、ドキュメントを格納するコレクションを作成します。insertOne()メソッドを使って、3件のドキュメントを挿入してみましょう。 > db.demo745.insertOne({Value1:100,Value2:100}); { acknowledged : true,