$elemMatch (投影)
定义
$elemMatch的
$elemMatch运算符限制了查询结果中<数组>字段的值,只包含符合$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") } )
以下投影在投影其他现有字段后返回 games 字段,尽管在文档中,该字段在 joined 和 lastLogin 字段之前列出
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 仅返回 students 数组中 school 字段值为 102 的第一个匹配元素
db.schools.find( { zipcode: "63109" }, { students: { $elemMatch: { school: 102 } } } )
操作返回以下具有 zipcode 值等于 63109 的文档,并使用 $elemMatch: 投影 students 数组
{ "_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字段,因为在它的students数组中没有元素匹配$elemMatch条件。
$elemMatch 与多个字段
$elemMatch 投影可以指定多个字段的准则
以下 find() 操作查询所有 zipcode 字段值为 63109 的文档。投影包括 students 数组中 school 字段值为 102 且 age 字段大于 10 的第一个匹配元素
db.schools.find( { zipcode: "63109" }, { students: { $elemMatch: { school: 102, age: { $gt: 10} } } } )
操作返回三个具有 zipcode 值等于 63109 的文档
{ "_id" : 1, "students" : [ { "name" : "jess", "school" : 102, "age" : 11 } ] } { "_id" : 3 } { "_id" : 4, "students" : [ { "name" : "ruth", "school" : 102, "age" : 16 } ] }
_id 等于 3 的文档不包含 students 字段,因为数组中没有元素匹配 $elemMatch 准则。
db.schools.find( { zipcode: "63109" }, { athletics: { $elemMatch: { athletics: "basketball" } } })
要匹配标量值,请使用相等运算符以及您想要匹配的标量值({$eq: <标量值>})。例如,以下find()操作查询所有zipcode字段值为63109的文档。投影包括值为basketball的athletics数组中的匹配元素。
db.schools.find( { zipcode: "63109" }, { athletics: { $elemMatch: { $eq: "basketball" } } })
操作返回三个具有 zipcode 值等于 63109 的文档
[ { _id : 1 }, { _id: 3, athletics: [ 'basketball' ] }, { _id : 4 } ]
具有_id等于3的文档是唯一符合《$elemMatch》条件的文档。