$elemMatch(プロジェクション)
定義
$elemMatch
$elemMatch
演算子は、クエリ結果の<array>
フィールドの内容を、$elemMatch
条件に一致する 最初の要素のみを含めるように制限します。
使用上の考慮事項
返される要素
$
演算子と$elemMatch
演算子の両方が、条件に基づいて配列から最初に一致する要素を投影します。
$
演算子は、クエリ ステートメントの条件に基づいて、コレクション内の各ドキュメントから最初に一致する配列要素を投影します。
$elemMatch
プロジェクション演算子は明示的な条件引数を受け取ります。これにより、クエリにない条件に基づいて投影したり、配列の埋め込みドキュメント内の複数のフィールドに基づいて投影したりすることができます。例については、「配列フィールドの制限」を参照してください。
フィールドの順序
ドキュメント内のフィールドの順序に関係なく、既存フィールドの $elemMatch
プロジェクションでは、他の既存フィールドを包含した後にフィールドが返されます。
たとえば、次のドキュメントを含む players
コレクションを考えます。
db.players.insertOne( { name: "player1", games: [ { game: "abc", score: 8 }, { game: "xyz", score: 5 } ], joined: new Date("2020-01-01"), lastLogin: new Date("2020-05-01") } )
次のプロジェクションでは、ドキュメントではjoined
フィールドとlastLogin
フィールドの前に フィールドがリストされているにもかかわらず、プロジェクションに含まれる他の既存フィールドの後にgames
フィールドが返されます。
db.players.find( {}, { games: { $elemMatch: { score: { $gt: 5 } } }, joined: 1, lastLogin: 1 } )
つまり、この操作は次のドキュメントを返します。
{ "_id" : ObjectId("5edef64a1c099fff6b033977"), "joined" : ISODate("2020-01-01T00:00:00Z"), "lastLogin" : ISODate("2020-05-01T00:00:00Z"), "games" : [ { "game" : "abc", "score" : 8 } ] }
制限事項
ビューにおける
db.collection.find()
操作は$elemMatch
プロジェクション演算子をサポートしていません。$elemMatch
では$text
クエリ演算子を指定できません
例
$elemMatch
プロジェクション演算子の例では、次のドキュメントを含むコレクションschools
を前提としています。
{ _id: 1, zipcode: "63109", students: [ { name: "john", school: 102, age: 10 }, { name: "jess", school: 102, age: 11 }, { name: "jeff", school: 108, age: 15 } ] } { _id: 2, zipcode: "63110", students: [ { name: "ajax", school: 100, age: 7 }, { name: "achilles", school: 100, age: 8 }, ], athletics: [ "swimming", "basketball", "football" ] } { _id: 3, zipcode: "63109", students: [ { name: "ajax", school: 100, age: 7 }, { name: "achilles", school: 100, age: 8 }, ], athletics: [ "baseball", "basketball", "soccer" ] } { _id: 4, zipcode: "63109", students: [ { name: "barney", school: 102, age: 7 }, { name: "ruth", school: 102, age: 16 }, ] }
郵便番号検索
次の find()
操作は、 zipcode
フィールドの値が 63109
であるすべてのドキュメントを照会します。$elemMatch
プロジェクションは、school
フィールドの値が 102
である students
配列の最初に一致する要素のみを返します。
db.schools.find( { zipcode: "63109" }, { students: { $elemMatch: { school: 102 } } } )
この操作では、zipcode
63109
が に等しい次のドキュメントが返され、 を使用してstudents
$elemMatch
配列がプロジェクションされます。
{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] } { "_id" : 3 } { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
_id
が1
に等しいドキュメントの場合、students
配列には、school
フィールドが102
に等しい複数の要素が含まれています。ただし、$elemMatch
プロジェクションは配列から最初に一致する要素のみを返します。_id
が3
に等しいドキュメントでは、students
配列のどの要素も$elemMatch
条件に一致しなかったため、結果にstudents
フィールドは含まれません。
$elemMatch
複数のフィールド付き
$elemMatch
プロジェクションは、複数のフィールドに条件を指定できます。
次の find()
操作は、 zipcode
フィールドの値が 63109
であるすべてのドキュメントを照会します。投影には、 school
フィールドの値が 102
で、age
フィールドの値が 10
より大きい students
配列の最初の一致する要素が含まれます。
db.schools.find( { zipcode: "63109" }, { students: { $elemMatch: { school: 102, age: { $gt: 10} } } } )
この操作では、次のように zipcode
が 63109
に等しい 3 つのドキュメントが返されます。
{ "_id" : 1, "students" : [ { "name" : "jess", "school" : 102, "age" : 11 } ] } { "_id" : 3 } { "_id" : 4, "students" : [ { "name" : "ruth", "school" : 102, "age" : 16 } ] }
が_id
3
students
に等しいドキュメントには、 条件に一致する配列要素がなかったため、$elemMatch
フィールドは含まれていません。
$elemMatch
への引数は、 $elemMatch
がプロジェクションしている配列の要素と一致します。 フィールド名で等価性を$elemMatch
に指定すると、配列内のオブジェクトの一致が試行されます。 たとえば、 $elemMatch
は、プロジェクションの次の配列内で、スカラー値ではなくオブジェクトを照合しようとします。
db.schools.find( { zipcode: "63109" }, { athletics: { $elemMatch: { athletics: "basketball" } } })
スカラー値をマッチングするには、等価演算子と一致させるスカラー値をマッチングします( {$eq: <scalar value>}
)。 たとえば、次のfind()
操作は、 zipcode
フィールドの値が63109
であるすべてのドキュメントを照会します。 投影には、値がbasketball
であるathletics
配列の一致する要素が含まれます。
db.schools.find( { zipcode: "63109" }, { athletics: { $elemMatch: { $eq: "basketball" } } })
この操作では、次のように zipcode
が 63109
に等しい 3 つのドキュメントが返されます。
[ { _id : 1 }, { _id: 3, athletics: [ 'basketball' ] }, { _id : 4 } ]
_id
が3
に等しいドキュメントが、 $elemMatch
条件に一致した唯一のドキュメントです。