Docs 菜单

Docs 主页开发应用程序MongoDB Manual

$(投影)

在此页面上

  • 定义
  • 使用注意事项
  • 行为
  • 举例
  • 深入阅读
$

位置 $操作符限制<array>的内容,以返回与数组上的查询条件匹配的第一个元素。

当您仅需要选定文档中的一个特定数组元素时,请在 findOne()方法或$ 方法的find() 投影 文档中使用 。

要返回仅包含与指定条件匹配的元素的数组,请参阅聚合操作符 $filter

注意

消歧

要指定要更新的数组元素,请参阅更新的位置 $ 操作符

$操作符和$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 要求满足以下条件:

  • 投影文档中只能出现一个位置$操作符。

  • 查询文档中只能出现一个数组字段。查询文档中的额外数组字段可能会导致未定义的行为。

    例如,以下投影可能会导致未定义的行为:

    db.collection.find( { <array>: <value>, <someOtherArray>: <value2> },
    { "<array>.$": 1 } )
  • 查询文档只应包含一个要应用于数组字段的条件。多个条件可能会在内部相互覆盖,并导致未定义的行为。

    要为数组内的多个文档字段指定条件,请使用 $elemMatch 查询运算符。以下查询返回 grades 数组中第一个符合以下条件的文档: mean 大于 70 且 grade 大于 90。

    db.students.find( { grades: { $elemMatch: {
    mean: { $gt: 70 },
    grade: { $gt:90 }
    } } },
    { "grades.$": 1 } )

    如需为选择文档和选择这些文档中的字段分别设置条件,则须使用 $elemMatch 运算符。

find() 方法包含sort() 时,find() 方法会在应用位置sort() 投影操作符 之前 $应用 对匹配文档进行排序。

如果数组字段包含多个具有相同字段名称的文档,并且find()方法在该重复字段上包含sort() ,则返回的文档可能无法反映排序顺序,因为排序是在$投影操作符。

$投影操作符只能出现在字段路径的末尾,例如"field.$""fieldA.fieldB.$"

例如,以下操作无效:

db.inventory.find( { }, { "instock.$.qty": 1 } )

要解决此问题,请删除字段路径中位于$投影运算符之后的部分。

findfindAndModify投影不能包含$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 字段是文档数组;每个文档包含三个字段名称 grademeanstd

{ "_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 } ] }

$elemMatch (projection)

← 投影操作符