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

ネストされた配列のすべての要素が条件に一致するオブジェクトをフィルタリングするMongoDBクエリ

ネストされた配列のすべての要素が特定の条件に一致するドキュメントだけを抽出したい場合は、aggregate() を活用するのが効果的です。まずは、サンプルデータを含むコレクションを作成してみましょう。

> db.demo418.insertOne(
   {
      "details":[
         {
            "CountryName":"US",
            "Marks":45
         },
         {
            "CountryName":"US",
            "Marks":56
         }
      ],
      "Name":"John"
   }
);
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e724324b912067e57771ae6")
}
> db.demo418.insertOne(
   {
      "details":[
         {
            "CountryName":"US",
            "Marks":78
         },
         {
            "CountryName":"UK",
            "Marks":97
         }
      ],
      "Name":"Mike"
   }
);
{
   "acknowledged" : true,
   "insertedId" : ObjectId("5e724325b912067e57771ae7")
}

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

> db.demo418.find();

これにより、次のような出力が得られます。

{ "_id" : ObjectId("5e724324b912067e57771ae6"), "details" : [ { "CountryName" : "US", "Marks" : 45 }, { "CountryName" : "US", "Marks" : 56 } ], "Name" : "John" }
{ "_id" : ObjectId("5e724325b912067e57771ae7"), "details" : [ { "CountryName" : "US", "Marks" : 78 }, { "CountryName" : "UK", "Marks" : 97 } ], "Name" : "Mike" }

出力を見ると、John の details 配列には「US」の要素のみが含まれている一方で、Mike の配列には「US」と「UK」が混在していることがわかります。今回の目的は、配列内の全要素が条件を満たすドキュメントだけを取り出すことです。

ネストされた配列の全要素が条件に一致するドキュメントをフィルタリングするクエリ

以下は、ネストされた配列のすべての要素が条件(ここでは CountryName が "US")に一致するドキュメントをフィルタリングする集計クエリです。

> db.demo418.aggregate([
   {$unwind:"$details"},
   { $group: {
      _id: '$_id',
      details : { $first: '$details' },
      alldetails: { $sum: 1 },
      alldetailsmatch: { $sum: { $cond: [ { $eq: [ '$details.CountryName', "US" ] }, 1, 0 ] } },
      Name: { $first: '$Name' }
   }},
   { $project: {
      _id: 1,
      Name: 1,
      details: 1,
      arrayValue: { $cond: [ { $eq: [ '$alldetails', '$alldetailsmatch' ] }, 1, 0 ] }
   }},
   { $match: { 'arrayValue' : 1 } }
])

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

{ "_id" : ObjectId("5e724324b912067e57771ae6"), "details" : { "CountryName" : "US", "Marks" : 45 }, "Name" : "John", "arrayValue" : 1 }

期待どおり、配列の全要素が "US" である John のドキュメントだけが取得できました。

クエリの仕組み

  • $unwind: details 配列を展開し、各要素を個別のドキュメントとして扱えるようにします。
  • $group: _id ごとにグループ化し、配列の総要素数(alldetails)と条件に一致した要素数(alldetailsmatch)をそれぞれカウントします。
  • $project: 総要素数と一致数が等しい場合に arrayValue を 1、そうでなければ 0 とします。
  • $match: arrayValue が 1 のドキュメント、つまり配列の全要素が条件に一致するドキュメントのみを最終結果として出力します。

この手法を使えば、「配列内の一部ではなく全部が条件を満たす」という厳密なフィルタリングを、シンプルなアグリゲーションパイプラインで実現できます。

  1. MongoDBでネストされた配列をソートする方法:$unwindと$sortを活用したクエリ

    MongoDBでドキュメント内に格納されたネストされた配列(サブドキュメントの配列)をソートしたい場合、集計パイプライン(aggregate)を使い、$unwindで配列を展開した後に$sortで並べ替え、最後に$groupで再構成するのが定番のアプローチです。この記事では、実際にコレクションを作成しながら、ネストされた配列をスコア順にソートする手順を解説します。1. サンプルコレクションの作成まず、ネストされた配列「details」を持つドキュメントを挿入してコレクションを作成します。> db.demo505.insertOne( ... { ... details: [ ..

  2. MySQLクエリで配列の要素をすべて一致させる方法

    MySQLでは、WHERE IN句とGROUP BY、HAVING句を組み合わせることで、指定した配列(複数の値)のすべての要素に一致するレコードを持つIDを抽出できます。この記事では、具体的なサンプルを使ってその手順を解説します。 1. サンプルテーブルを作成する まず、以下のコマンドでテーブル「DemoTable1523」を作成します。 mysql> create table DemoTable1523 -> ( -> Id int, -> Value int -> ); Query OK, 0 rows affected (