定義
$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 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 }, ] }
次の C# クラスを使用して、これらのドキュメントをモデル化できます。
public class School { public string Id { get; set; } [] public string ZipCode { get; set; } public Student[] Students { get; set; } public string[] Athletics { get; set; } }
public class Student { public string Id { get; set; } public string Name { get; set; } public int School { get; set; } public int Age { get; set; } }
郵便番号検索
find()次のzipcode 操作は、 フィールドの値が"63109" であるすべてのドキュメントを照会します。 プロジェクションは、$elemMatch フィールドの値が である 配列の最初に一致する要素のみを返します。studentsschool102
db.schools.find( { zipcode: "63109" }, { students: { $elemMatch: { school: 102 } } } )
.NET/ C#ドライバーを使用して $elemMatchプロジェクションを実行するには、プロジェクションビルダで ElemMatch() メソッドを呼び出します。プロジェクトを行う配列フィールドの名前と、配列要素に適用するフィルターを渡します。
次のコード例では、Zipcode フィールドの値が "63109" であるすべてのドキュメントを検索します。各一致ドキュメントに対して、プロジェクションは以下のフィールドを返します。
Idネストされた
Schoolフィールドの値が102である値を持つStudents配列の最初の要素
var results = schoolsCollection .Find(s => s.ZipCode == "63109") .Project(Builders<School>.Projection.ElemMatch( field: school => school.Students, filter: student => student.School == 102 ) ).ToList();
この操作では、zipcode 値が である次のドキュメントが返され、"63109" を使用してstudents $elemMatch配列がプロジェクションされます。
{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] } { "_id" : 3 } { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
が に等しいドキュメントの場合、
_id1students配列にはschool102$elemMatchフィールドが に等しい複数の要素が含まれています。ただし、 プロジェクションは配列から最初に一致する要素のみを返します。が
$elemMatch_id3studentsに等しいドキュメントは、 配列内のどの要素も 条件に一致しなかったため、結果に フィールドが含まれていません。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" であるすべてのドキュメントを検索します。各一致ドキュメントに対して、プロジェクションは以下のフィールドを返します。
IdStudents配列の最初の要素で、ネストされたSchoolフィールドの値が102であり、Ageフィールドの値が10より大きい
var results = schoolsCollection .Find(s => s.ZipCode == "63109") .Project(Builders<School>.Projection.ElemMatch( field: school => school.Students, filter: student => (student.School == 102) && (student.Age > 10) ) ).ToList();
この操作では、次のように、zipcode の値が "63109" である 3 つのドキュメントが返されます。
{ "_id" : 1, "students" : [ { "name" : "jess", "school" : 102, "age" : 11 } ] } { "_id" : 3 } { "_id" : 4, "students" : [ { "name" : "ruth", "school" : 102, "age" : 16 } ] }
が_id 3studentsに等しいドキュメントには、 条件に一致する配列要素がなかったため、$elemMatch フィールドは含まれていません。
$elemMatch$elemMatchの引数は、 がプロジェクションしている配列の要素と一致します。フィールド名で等価性を$elemMatch に指定すると、配列内のオブジェクトとの一致が試行されます。例、 は、プロジェクションの次の配列内で、スカラー値ではなくオブジェクトを照合しようとします。$elemMatch
db.schools.find( { zipcode: "63109" }, { athletics: { $elemMatch: { athletics: "basketball" } } })
var results = schoolsCollection .Find(s => s.ZipCode == "63109") .Project(Builders<School>.Projection.ElemMatch( "athletics", Builders<School>.Filter.Eq("athletics", "basketball")) ).ToList();
上記の例では、zipcode 値が "63109" であるドキュメントが返されますが、プロジェクション操作では一致する要素が見つからなかったため、これらのドキュメントには _idフィールドのみが含まれます。
スカラー値をマッチングするには、等価演算子と一致させるスカラー値をマッチングします( {$eq: <scalar value>} )。 たとえば、次のfind()操作は、 zipcodeフィールドの値が"63109"であるすべてのドキュメントを照会します。 投影には、値がbasketballであるathletics配列の一致する要素が含まれます。
db.schools.find( { zipcode: "63109" }, { athletics: { $elemMatch: { $eq: "basketball" } } })
.NET/C# ドライバーを使用して配列内のスカラー値に対して $elemMatch 操作を実行するには、プロジェクション ビルダーの ElemMatch() メソッドを呼び出します。プロジェクトする配列フィールドの名前と、フィールド "$eq" の等価フィルター、および比較対象の値を渡します。
var results = schoolsCollection .Find(s => s.ZipCode == "63109") .Project(Builders<School>.Projection.ElemMatch( field: "athletics", filter: Builders<School>.Filter.Eq("$eq", "basketball")) ).ToList();
この操作では、zipcode の値が "63109" である 3 つのドキュメントが返されます。返されるドキュメントには、_id フィールドと athletics 配列の一致する要素(存在する場合)が含まれます。
[ { _id: 1 }, { _id: 3, athletics: [ 'basketball' ] }, { _id: 4 } ]
が_id 3に等しいドキュメントが、$elemMatch 条件に一致した唯一のドキュメントです。
Tip
$ (projection) 演算子