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

MongoDBでサブ配列(ネストされた配列)の値を抽出する方法 – $elemMatch演算子の使い方

MongoDBでは、ドキュメント内にネストされた配列(サブ配列)から特定の要素だけを取り出したいケースがよくあります。そんなときに活躍するのが、プロジェクション演算子 $elemMatch です。この記事では、実際のコード例を使いながら、$elemMatch を使ったサブ配列の抽出方法をわかりやすく解説します。

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

まずは、クライアント情報とそのプロジェクト詳細を配列として持つコレクションを作成しましょう。insertOne() メソッドを使用してドキュメントを挿入します。

> db.extractSubArrayDemo.insertOne(
...     {
...         _id: 101,
...         "clientName": "Larry",
...         "ClientDetails":
...         [
...             {
...                 "ClientProjectName": "Online Game",
...                 "DeveloperTeamSize": 10
...             },
...             {
...                 "ClientProjectName": "Pig Dice Game",
...                 "DeveloperTeamSize": 12
...             },
...             {
...                 "ClientProjectName": "Web Student Tracker",
...                 "DeveloperTeamSize": 11
...             }
...         ]
...     }
... );
{ "acknowledged" : true, "insertedId" : 101 }

挿入に成功すると、acknowledged: true と挿入されたドキュメントの _id が返されます。

2. find()メソッドで全ドキュメントを確認

次に、find() メソッドを使ってコレクション内のすべてのドキュメントを表示してみます。pretty() を付けると、結果が整形されて読みやすくなります。

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

実行すると、以下のような出力が得られます。

{
    "_id" : 101,
    "clientName" : "Larry",
    "ClientDetails" : [
        {
            "ClientProjectName" : "Online Game",
            "DeveloperTeamSize" : 10
        },
        {
            "ClientProjectName" : "Pig Dice Game",
            "DeveloperTeamSize" : 12
        },
        {
            "ClientProjectName" : "Web Student Tracker",
            "DeveloperTeamSize" : 11
        }
    ]
}

このように、ClientDetails 配列には3つのプロジェクト情報が格納されています。ここから特定のプロジェクトだけを抽出するのが次のステップです。

3. $elemMatchでサブ配列の値を抽出する

それでは本題です。以下のクエリでは、第2引数のプロジェクション部分で $elemMatch を使用し、「Pig Dice Game」というプロジェクト名に一致する要素のみを ClientDetails 配列から取り出しています。また、_id: 0 を指定することで、_id フィールドを出力から除外しています。

> db.extractSubArrayDemo.find({ '_id': 101 },{ _id: 0, ClientDetails:
    { $elemMatch: {ClientProjectName: 'Pig Dice Game' } }}).pretty();

実行結果は以下の通りです。

{
    "ClientDetails" : [
        {
            "ClientProjectName" : "Pig Dice Game",
            "DeveloperTeamSize" : 12
        }
    ]
}

条件に一致した要素だけが配列として返され、それ以外の「Online Game」や「Web Student Tracker」は出力されていないことが確認できます。

$elemMatchのポイントと注意点

  • 単一要素の返却: プロジェクションでの $elemMatch は、条件に一致した最初の1件のみを返します。複数件を取得したい場合は後述の集計パイプラインを検討してください。
  • 複数条件の組み合わせ: $elemMatch の内部では、{ "DeveloperTeamSize": { $gte: 11 } } のように他の条件演算子と組み合わせることも可能です。
  • フィールド除外との併用: 上記の例のように _id: 0 を指定すれば、不要なフィールドを結果から除けます。

補足:複数の一致要素を取得したい場合

プロジェクションの $elemMatch は最初の一致要素しか返せないため、条件に合うすべての要素が必要な場合は、MongoDB 3.2以降で利用できる $filter 演算子を集計パイプライン(aggregate)で使う方法がおすすめです。

> db.extractSubArrayDemo.aggregate([
...   { $match: { _id: 101 } },
...   { $project: {
...       _id: 0,
...       ClientDetails: {
...           $filter: {
...               input: "$ClientDetails",
...               as: "detail",
...               cond: { $eq: ["$$detail.DeveloperTeamSize", 12] }
...           }
...       }
...   }}
... ]);

このように用途に応じて $elemMatch と $filter を使い分けることで、ネストされた配列データを柔軟に扱えるようになります。

まとめ

MongoDBでサブ配列から特定の値を抽出するには、find() メソッドのプロジェクションで $elemMatch を使用するのが最もシンプルな方法です。最初の一致要素のみの取得という制限がある点さえ押さえておけば、クライアント情報や注文明細など、配列を持つドキュメントの操作で非常に役立ちます。複数件の取得が必要な場合は、$filter を使った集計パイプラインも併せて覚えておくとよいでしょう。

  1. MongoDBで範囲検索を行う方法:sort()とlimit()の組み合わせ

    MongoDBで範囲検索を行う方法MongoDBで範囲検索(特定の値以下・以上のドキュメントを取得する検索)を行うには、比較演算子とsort()、limit()を組み合わせて使用します。ここでは、実際のサンプルコードを使いながら手順を詳しく解説します。1. サンプルコレクションの作成まず、insertOne()メソッドを使って、ドキュメントを含むコレクションを作成しましょう。> db.demo665.insertOne({"Value":10}); { "acknowledged" : true, "insertedId&qu

  2. MongoDBで配列の値を使ってコレクションを並べ替える方法

    MongoDBのコレクションを配列の値を基準にソートしたい場合は、aggregate()メソッドと $sort ステージを組み合わせて使用します。さらに、配列を個々のドキュメントに分解するために $unwind も活用します。 サンプルコレクションの作成 まず、ドキュメントを含むコレクションを作成しましょう。ここでは、学生ごとの詳細情報(名前とスコア)を配列として持つドキュメントを挿入します。 > db.demo577.insertOne( ... { ... student: { ... details: [ ... { .