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

MongoDBの$unwindで2つの配列を展開する方法を実例付きで解説

MongoDBでは、アンワインド(unwind)とは、入力ドキュメントに含まれる配列フィールドを分解し、配列の各要素ごとに個別のドキュメントを出力する処理を指します。ネストされた配列データを行単位のデータとして扱いたい場合に非常に便利な機能です。

配列をアンワインドするには、MongoDBのアグリゲーションパイプライン$unwind ステージを使用します。さらに、複数の配列を同時に展開した上で、対応する要素同士を組み合わせたい場合は $match$expr を組み合わせることで実現できます。

サンプルコレクションの作成

まず、2つの配列フィールド「Details1」と「Details」を持つドキュメントを含むコレクションを作成します。

> db.demo387.insertOne(
...     {
...        "Name" : "101",
...        "Details1" : [
...           {Value:100, Value1:50, Value2:40},
...           {Value:200},
...           {Value:300}
...        ],
...        "Details" : [
...           {Value:100, Value1:30, Value2:26},
...           {Value:200},
...           {Value:300}
...        ]
...     }
... );
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e5d197022064be7ab44e7f8")
}

登録したドキュメントの確認

find() メソッドを使って、コレクション内のすべてのドキュメントを表示してみましょう。

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

このクエリを実行すると、次のような出力が得られます。

{
   "_id" : ObjectId("5e5d197022064be7ab44e7f8"),
   "Name" : "101",
   "Details1" : [
      {
         "Value" : 100,
         "Value1" : 50,
         "Value2" : 40
      },
      {
         "Value" : 200
      },
      {
         "Value" : 300
      }
   ],
   "Details" : [
      {
         "Value" : 100,
         "Value1" : 30,
         "Value2" : 26
      },
      {
         "Value" : 200
      },
      {
         "Value" : 300
      }
   ]
}

複数の配列を展開するアグリゲーションクエリ

それでは、2つ以上の配列を持つドキュメントを展開し、特定の条件で絞り込むアグリゲーションクエリを見ていきましょう。以下の例では、$Details1$Details の両方を $unwind で展開した後、$match$expr を使って、両方の配列で Value の値が一致する組み合わせのみを抽出しています。

> db.demo387.aggregate([
...    { "$unwind": "$Details1" },
...    { "$unwind": "$Details" },
...    { "$match": { "$expr":
...       { "$eq": ["$Details1.Value", "$Details.Value"] }
...    }}
... ])

ポイント:複数の $unwind を連続して適用すると、それぞれの配列の全要素の組み合わせ(直積)が生成されます。そのため、意図しない大量のドキュメントが発生する可能性があります。$match を組み合わせて必要なペアだけを抽出するのが実践的なテクニックです。

実行結果

上記のクエリを実行すると、次のように Value の値が一致する要素のペアだけが出力されます。

{ "_id" : ObjectId("5e5d197022064be7ab44e7f8"), "Name" : "101", "Details1" : { "Value" : 100, "Value1" : 50, "Value2" : 40 }, "Details" : { "Value" : 100, "Value1" : 30, "Value2" : 26 } }
{ "_id" : ObjectId("5e5d197022064be7ab44e7f8"), "Name" : "101", "Details1" : { "Value" : 200 }, "Details" : { "Value" : 200 } }
{ "_id" : ObjectId("5e5d197022064be7ab44e7f8"), "Name" : "101", "Details1" : { "Value" : 300 }, "Details" : { "Value" : 300 } }

このように、$unwind を複数回使用すれば1つのドキュメント内の複数の配列を展開でき、$match + $expr の組み合わせによって配列間で関連性のある要素だけを効率よく取り出すことができます。レポート作成やデータの正規化処理など、さまざまなユースケースで活用できるので、ぜひ覚えておきましょう。

  1. MongoDBで_idを使ってグループ化するクエリの書き方

    MongoDBでドキュメントをグループ化するには、集計パイプライン(aggregation pipeline)の $group ステージを使用します。この記事では、実際にコレクションを作成し、$group を使ってデータを集計する手順を具体的な例とともに解説します。 サンプルコレクションの作成 まずは、動作確認用のコレクションにドキュメントを挿入してみましょう。以下のように insertOne() メソッドを使って、スコア情報を持つドキュメントを複数件登録します。 > db.demo529.insertOne({Score:10}); { acknowledged : true

  2. MongoDBでコレクションの名前を変更する方法(renameCollectionの使い方)

    MongoDBで既存のコレクションの名前を変更したい場合、renameCollection()メソッドを使用します。この記事では、実際にコレクションを作成し、その名前を変更するまでの手順を順番に解説します。1. ドキュメントを含むコレクションを作成するまず、insertOne()メソッドを使ってサンプルドキュメントを挿入し、コレクション「demo690」を作成します。> db.demo690.insertOne({_id:101,Name:Sam}); { acknowledged : true, insertedId : 101 } > db.demo690.insertOne(