MongoDBで配列内の要素に特定のフィールドが存在しないドキュメントを検索するクエリ
MongoDBでは、配列内の一部の要素だけに特定のフィールドが存在しないようなドキュメントを検索したいケースがあります。たとえば、日付(DueDate)はあるものの価格(ProductPrice)が設定されていない要素を含むドキュメントを探す場合などです。
このような場合には、$elemMatch 演算子と $exists 演算子を組み合わせて使用します。$elemMatch は、指定したすべてのクエリ条件に一致する要素を少なくとも1つ含む配列フィールドを持つドキュメントに一致させます。さらに、$exists を使うことで「フィールドが存在する/存在しない」という条件を表現できます。
サンプルコレクションの作成
まず、ドキュメントを含むコレクションを作成しましょう。
> db.demo239.insertOne(
... {
... "Name" : "Chris",
... "details" : [
... { "DueDate" : new ISODate("2019-01-21"), "ProductPrice" : 1270 },
... { "DueDate" : new ISODate("2020-02-12"), "ProductPrice" : 2000 }
... ]
... }
...);
{
"acknowledged" : true,
"insertedId" : ObjectId("5e441c6bf4cebbeaebec5157")
}
> db.demo239.insertOne(
... {
... "Name" : "David",
... "details" : [
... { "DueDate" : new ISODate("2018-11-11"), "ProductPrice" : 1450},
... { "DueDate" : new ISODate("2020-02-12") }
... ]
... }
...);
{
"acknowledged" : true,
"insertedId" : ObjectId("5e441c6cf4cebbeaebec5158")
}上記の例では、2件のドキュメントを挿入しています。ポイントは2つ目の「David」のドキュメントで、details 配列の2番目の要素には DueDate のみが存在し、ProductPrice フィールドがありません。
find()メソッドですべてのドキュメントを表示する
find() メソッドを使って、コレクション内のすべてのドキュメントを表示してみます。
> db.demo239.find();
これにより、次のような出力が得られます。
{
"_id" : ObjectId("5e441c6bf4cebbeaebec5157"), "Name" : "Chris", "details" : [
{ "DueDate" : ISODate("2019-01-21T00:00:00Z"), "ProductPrice" : 1270 },
{ "DueDate" : ISODate("2020-02-12T00:00:00Z"), "ProductPrice" : 2000 }
]
}
{
"_id" : ObjectId("5e441c6cf4cebbeaebec5158"), "Name" : "David", "details" : [
{ "DueDate" : ISODate("2018-11-11T00:00:00Z"), "ProductPrice" : 1450 },
{ "DueDate" : ISODate("2020-02-12T00:00:00Z") }
]
}特定のフィールドを持たない配列要素を検索するクエリ
続いて、配列内の要素に特定のフィールド(ここでは ProductPrice)が存在しないドキュメントを取得するクエリを見てみましょう。
> db.demo239.find({ "details": { "$elemMatch": { "DueDate": { "$exists": true }, "ProductPrice": { "$exists": false } } } })このクエリの意味は以下のとおりです。
- DueDate: { $exists: true } … 配列要素に DueDate フィールドが存在すること
- ProductPrice: { $exists: false } … 同じ要素に ProductPrice フィールドが存在しないこと
$elemMatch を使うことで、「同一の要素内」でこれら両方の条件が満たされる場合のみ一致します。単純に details.ProductPrice: { $exists: false } と書いた場合は、配列の別々の要素に対して条件が評価されてしまうため、意図した結果にならないことがあります。この点が $elemMatch を使う重要な理由です。
実行すると、次の出力が得られます。
{ "_id" : ObjectId("5e441c6cf4cebbeaebec5158"), "Name" : "David", "details" : [ { "DueDate" : ISODate("2018-11-11T00:00:00Z"), "ProductPrice" : 1450 }, { "DueDate" : ISODate("2020-02-12T00:00:00Z") } ] }結果として、ProductPrice が存在しない要素を含む「David」のドキュメントのみが返されました。「Chris」のドキュメントは、details 配列のすべての要素に ProductPrice が存在するため、条件に一致していません。
まとめ
配列内の要素に特定のフィールドが存在しないドキュメントを検索するには、$elemMatch で配列要素に対する複数条件をまとめ、$exists 演算子でフィールドの有無を判定します。この組み合わせを覚えておくと、部分的なデータが欠落しているドキュメントの抽出やデータ品質チェックなど、さまざまな場面で役立ちます。
-
MongoDBでオブジェクト配列内の特定のネストされたドキュメントをクエリする方法
MongoDBでオブジェクトの配列からネストされたドキュメントを抽出する オブジェクトの配列に格納されたネストされたドキュメントを条件付きで検索したい場合、find()メソッドに$elemMatch演算子を組み合わせることで、指定した条件に一致する要素だけを取り出すことができます。 ここでは、「StudentAge」フィールドを持つ学生情報だけを配列から抽出する例を見ていきましょう。 1. サンプルコレクションの作成 まず、ドキュメントを挿入してコレクションを作成します。このコレクションには、学生情報がオブジェクトの配列として格納されています。 > db.demo763.insertO
-
MongoDBで配列をクエリして特定の値を取得する方法
配列から特定の値を取得するには、aggregate()メソッドと$projectステージを組み合わせて使用します。まずは、ドキュメントを含むコレクションを作成してみましょう。 > db.demo761.insertOne( ... { ... "details": [ ... { ... "