$(プロジェクション)
定義
使用上の考慮事項
$
演算子と$elemMatch
演算子の両方が、条件に基づいて配列から最初に一致する要素を投影します。
$
演算子は、クエリ ステートメントの条件に基づいて、コレクション内の各ドキュメントから最初に一致する配列要素を投影します。
$elemMatch
プロジェクション演算子は明示的な条件引数を受け取ります。これにより、クエリにない条件に基づいて投影したり、配列の埋め込みドキュメント内の複数のフィールドに基づいて投影したりすることができます。例については、「配列フィールドの制限」を参照してください。
ビューにおける db.collection.find()
操作は $
プロジェクション演算子をサポートしていません。
動作
構文
配列上の指定されたクエリ条件に一致する最初の配列要素を返すには、
db.collection.find( { <array>: <condition> ... }, { "<array>.$": 1 } ) db.collection.find( { <array.field>: <condition> ...}, { "<array>.$": 1 } )
$
演算子を使用して、クエリ ドキュメントに表示されない<array>
フィールドを制限できます。 以前のバージョンの MongoDB では、制限されている<array>
フィールドがクエリ ドキュメントに表示される必要があります。
db.collection.find( { <someOtherArray>: <condition> ... }, { "<array>.$" : 1 } )
重要
期待どおりの動作を実現するには、クエリドキュメントとプロジェクションドキュメントで使用される配列が同じ長さである必要があります。 配列の長さが異なる場合、特定のシナリオでは操作でエラーが発生する可能性があります。
配列フィールドの制限
MongoDB では、配列へのプロジェクションを処理するときに次のものが必要です。
プロジェクション ドキュメントには、位置演算子の
$
を 1 つだけ使用できます。クエリドキュメントには、配列フィールドを 1 つだけ表示する必要があります。クエリ ドキュメント内の追加の配列フィールドにより、未定義の動作が発生する可能性があります。
例えば、次のプロジェクションは未定義の動作につながる可能性があります。
db.collection.find( { <array>: <value>, <someOtherArray>: <value2> }, { "<array>.$": 1 } ) クエリドキュメントには、それが適用される配列フィールドに 1 つの条件のみを含める必要があります。複数の条件が内部的に互いに上書きされ、未定義の動作が発生する可能性があります。
配列内のドキュメントの複数のフィールドに条件を指定するには、
$elemMatch
クエリ演算子を使用します。次のクエリは、grades
配列内のmean
が 70 より大きくgrade
が 90 より大きい最初のドキュメントを返します。db.students.find( { grades: { $elemMatch: { mean: { $gt: 70 }, grade: { $gt:90 } } } }, { "grades.$": 1 } ) ドキュメントの選択とそれらのドキュメント内のフィールドの選択に別々の条件が必要な場合は、
$elemMatch
演算子を使用する必要があります。
sorts と位置演算子
find()
メソッドにsort()
が含まれている場合、 find()
メソッドはsort()
を適用して一致するドキュメントを順序付けてから、位置指定の$
プロジェクション演算子を適用します。
配列フィールドに同じフィールド名を持つ複数のドキュメントが含まれており、 find()
メソッドにその繰り返しフィールドにsort()
が含まれている場合、返されるドキュメントがソート順序を反映していない可能性があります。これは、ソートが$
プロジェクション演算子。
位置演算子の配置制限
$
プロジェクション演算子は、フィールドパスの末尾にのみ使用できます(例: "field.$"
または"fieldA.fieldB.$"
。
たとえば、次の操作は無効です。
db.inventory.find( { }, { "instock.$.qty": 1 } )
解決するには、$
プロジェクション演算子の後に続くフィールドパスのコンポーネントを削除します。
位置演算子と$slice
の制限
find
プロジェクションと findAndModify
プロジェクションには、$
プロジェクション式の一部として $slice
プロジェクション式を含めることはできません。
たとえば、次の操作は無効です。
db.inventory.find( { "instock.qty": { $gt: 25 } }, { "instock.$": { $slice: 1 } } )
以前のバージョンでは、MongoDB はクエリ条件に一致する instock
配列の最初の要素(instock.$
)を返します。つまり、位置プロジェクション"instock.$"
が優先され、$slice:1
の処理はありません。"instock.$": {
$slice: 1 }
は他のドキュメント フィールドを除外しません。
例
プロジェクト配列の値
コレクション students
には次のドキュメントが含まれています。
{ "_id" : 1, "semester" : 1, "grades" : [ 70, 87, 90 ] } { "_id" : 2, "semester" : 1, "grades" : [ 90, 88, 92 ] } { "_id" : 3, "semester" : 1, "grades" : [ 85, 100, 90 ] } { "_id" : 4, "semester" : 2, "grades" : [ 79, 85, 80 ] } { "_id" : 5, "semester" : 2, "grades" : [ 88, 88, 92 ] } { "_id" : 6, "semester" : 2, "grades" : [ 95, 90, 96 ] }
次のクエリでは、プロジェクション{ "grades.$": 1 }
は、 grades
フィールドの85
以上の最初の要素のみを返します。
db.students.find( { semester: 1, grades: { $gte: 85 } }, { "grades.$": 1 } )
この操作により、次のドキュメントが返されます。
{ "_id" : 1, "grades" : [ 87 ] } { "_id" : 2, "grades" : [ 90 ] } { "_id" : 3, "grades" : [ 85 ] }
配列フィールド grades
には 85
以上の複数の要素が含まれる場合がありますが、$
プロジェクション演算子は一致する最初の要素のみを配列から返します。
プロジェクト配列ドキュメント
students
コレクションには、次のドキュメントが含まれ、grades
フィールドはドキュメントの配列です。各ドキュメントには、次の 3 つのフィールド名 grade
、 mean
、 std
が含まれています。
{ "_id" : 7, semester: 3, "grades" : [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 90, mean: 85, std: 3 } ] } { "_id" : 8, semester: 3, "grades" : [ { grade: 92, mean: 88, std: 8 }, { grade: 78, mean: 90, std: 5 }, { grade: 88, mean: 85, std: 3 } ] }
次のクエリでは、プロジェクション { "grades.$": 1 }
は grades
フィールドの mean
が 70
より大きい最初の要素のみを返します。
db.students.find( { "grades.mean": { $gt: 70 } }, { "grades.$": 1 } )
この操作により、次のドキュメントが返されます。
{ "_id" : 7, "grades" : [ { "grade" : 80, "mean" : 75, "std" : 8 } ] } { "_id" : 8, "grades" : [ { "grade" : 92, "mean" : 88, "std" : 8 } ] }