MongoDBでネストしたサブドキュメントをフィルタリングする方法(aggregateと$unwind活用)
MongoDBでは、配列の中にさらに配列(サブドキュメント)がネストしている構造を持つドキュメントから、特定の条件に合致する要素だけを抽出したいケースがあります。このような場合、aggregate()メソッドと$unwind演算子を組み合わせることで実現できます。
本記事では、実際のコード例を使いながら、ネストしたサブドキュメントのフィルタリング手順を解説します。
サンプルコレクションの作成
まず、ネストしたサブドキュメントを含むドキュメントを挿入して、コレクションを作成しましょう。
> db.demo583.insert([
... {
... "details1" : [
... {
... "details2" : [
... {
... "isMarried" : true,
... "Name" : "Chris"
... },
... {
... "isMarried" : true,
... "Name" : "Bob"
... }
... ]
... },
... {
... "details2" : [
... {
... "isMarried" : false,
... "Name" : "Chris"
... },
... {
... "isMarried" : true,
... "Name" : "Mike"
... }
... ]
... }
... ]
... }
... ]);
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 1,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})挿入したドキュメントの確認
find()メソッドを使って、コレクション内のすべてのドキュメントを表示してみます。
> db.demo583.find();
このクエリを実行すると、次のような出力が得られます。
{ "_id" : ObjectId("5e91d3c4fd2d90c177b5bcc1"), "details1" : [
{ "details2" : [
{ "isMarried" : true, "Name" : "Chris" },
{ "isMarried" : true, "Name" : "Bob" }
] },
{ "details2" : [
{ "isMarried" : false, "Name" : "Chris" },
{ "isMarried" : true, "Name" : "Mike" }
] }
] }サブドキュメント内のサブドキュメントをフィルタリングするクエリ
ここからが本題です。「isMarriedがtrueかつNameがChris」という条件に一致する要素のみを抽出するには、以下のような集計パイプラインを使用します。
> var q= [
... {
... "$match": {
... "details1.details2.isMarried": true,
... "details1.details2.Name": "Chris"
... }
... },
... {
... "$unwind": "$details1"
... },
... {
... "$unwind": "$details1.details2"
... },
... {
... "$match": {
... "details1.details2.isMarried": true,
... "details1.details2.Name": "Chris"
... }
... }
... ];
> db.demo583.aggregate(q).pretty();このクエリを実行すると、次の出力が得られます。
{
"_id" : ObjectId("5e91d3c4fd2d90c177b5bcc1"),
"details1" : {
"details2" : {
"isMarried" : true,
"Name" : "Chris"
}
}
}クエリの仕組みのポイント
このパイプラインが機能する仕組みは、以下の流れになっています。
1. 最初の$matchステージ: ドキュメント全体を対象に、条件に一致する可能性のあるドキュメントだけを早期に絞り込みます。これにより、後続の処理対象を減らし、パフォーマンスを向上させられます。
2. $unwindによる配列の展開: $unwindは、指定した配列フィールドの各要素を個別のドキュメントとして展開する演算子です。ここではdetails1と、その中のdetails2という二重の配列を順番に展開しています。
3. 二度目の$matchステージ: 展開後の個々のサブドキュメントに対して再度条件を適用することで、条件に合致しない要素を完全に除外します。これにより、「Chris(既婚)」という1件だけが最終結果として残ります。
このように、$unwindで配列を展開してから$matchで絞り込むのが、MongoDBでネストしたサブドキュメントを正確にフィルタリングする基本的なアプローチです。
-
MongoDBのaggregate()で3階層にネストされた埋め込みドキュメントの配列をフィルタリングする方法
MongoDBでネストされた配列をフィルタリングする基本アプローチMongoDBで3階層にネストされた埋め込みドキュメントの配列をフィルタリングするには、aggregate()メソッドを使用します。集計パイプラインの中で$unwindによって配列を展開し、$matchで条件に一致するドキュメントを絞り込むのが基本的な流れです。この記事では、実際のコード例を通じて具体的な手順を解説します。1. サンプルコレクションの作成まずは動作確認用のコレクションを作成し、ドキュメントを挿入してみましょう。> db.demo736.insertOne( ... { ... _id:
-
MongoDBドキュメントから特定の値をフィルタリングする方法
MongoDBドキュメントから特定の値をフィルタリングする方法MongoDBでドキュメント内の配列から特定の値を抽出したい場合は、集計パイプラインで $filter を使用します。この記事では、実際にコレクションを作成し、特定の条件に一致する要素だけをフィルタリングする手順を、サンプルコードとともに解説します。1. サンプルコレクションの作成まず、insertOne() メソッドを使って、配列フィールドを含むドキュメントを持つコレクションを作成します。 db.demo751.insertOne( ... { ... _id: 101, ... details: [