Docs 菜单
Docs 主页
/
MongoDB Manual
/ / / /

$elemMatch(投影)

在此页面上

  • 定义
  • 使用注意事项
  • 示例

提示

另请参阅:

$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")
} )

以下投影会在投影中包含的其他现有字段之后返回 games 字段,即使在文档中,该字段位于 joinedlastLogin 字段之前:

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 } ]
}

$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 字段的值为 102students 数组中的第一个匹配元素:

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 投影可指定针对多个字段的条件:

如下 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 条件相匹配。

$elemMatch的参数与$elemMatch所投影的大量元素相匹配。 如果将字段名称指定为$elemMatch的等式,则会尝试匹配大量中的对象。 示例, $elemMatch尝试为投影中的以下内容匹配大量中的对象而不是标量值:

db.schools.find( { zipcode: "63109" },
{ athletics: { $elemMatch: { athletics: "basketball" } } })

要匹配标量值,请使用相等操作符和要匹配的标量值 ( {$eq: <scalar value>} )。 示例,以下find()操作会查询zipcode字段的值为63109的所有文档。 投影包括athletics大量的匹配元素,其中值为basketball

db.schools.find( { zipcode: "63109" },
{ athletics: { $elemMatch: { $eq: "basketball" } } })

此操作将返回 zipcode 等于 63109 的三个文档:

[
{ _id : 1 },
{ _id: 3, athletics: [ 'basketball' ] },
{ _id : 4 }
]

_id等于3的文档是唯一符合$elemMatch条件的文档。

提示

另请参阅:

$ (projection) 运算符

后退

$