$project (aggregation)

On this page本页内容

Definition定义

$project

Passes along the documents with the requested fields to the next stage in the pipeline. 将带有请求字段的文档传递到管道中的下一个阶段。The specified fields can be existing fields from the input documents or newly computed fields.指定的字段可以是输入文档中的现有字段,也可以是新计算的字段。

The $project stage has the following prototype form:$project阶段具有以下原型形式:

{ $project: { <specification(s)> } }

The $project takes a document that can specify the inclusion of fields, the suppression of the _id field, the addition of new fields, and the resetting of the values of existing fields. $project获取一个文档,该文档可以指定包含字段、抑制_id字段、添加新字段以及重置现有字段的值。Alternatively, you may specify the exclusion of fields.或者,您可以指定字段的排除

The $project specifications have the following forms:$project规范有以下形式:

Form形式Description描述
<field>: <1 or true> Specifies the inclusion of a field.指定包含字段。
_id: <0 or false>

Specifies the suppression of the _id field.指定对_id字段的抑制。

To exclude a field conditionally, use the REMOVE variable instead. 要有条件地排除字段,请改用REMOVE变量。For details, see Exclude Fields Conditionally.有关详细信息,请参阅有条件排除字段

<field>: <expression>

Adds a new field or resets the value of an existing field.添加新字段或重置现有字段的值。

Changed in version 3.6.在版本3.6中更改。MongoDB 3.6 adds the variable REMOVE. MongoDB 3.6添加了变量REMOVEIf the the expression evaluates to $$REMOVE, the field is excluded in the output. 如果表达式的计算结果为$$REMOVE,则输出中将排除该字段。
For details, see Exclude Fields Conditionally.有关详细信息,请参阅有条件排除字段

<field>:<0 or false>

Specifies the exclusion of a field.指定字段的排除。

To exclude a field conditionally, use the REMOVE variable instead. 要有条件地排除字段,请改用REMOVE变量。
For details, see Exclude Fields Conditionally.有关详细信息,请参阅有条件排除字段

If you specify the exclusion of a field other than _id, you cannot employ any other $project specification forms. 如果指定排除_id以外的字段,则不能使用任何其他$project规范表单。This restriction does not apply to conditionally exclusion of a field using the REMOVE variable.此限制不适用于使用REMOVE变量有条件排除字段。

See also the $unset stage to exclude fields.另请参见$unset阶段以排除字段。

Considerations考虑事项

Include Existing Fields包括现有字段

  • The _id field is, by default, included in the output documents. 默认情况下,_id字段包含在输出文档中。To include any other fields from the input documents in the output documents, you must explicitly specify the inclusion in $project.要在输出文档中包含输入文档中的任何其他字段,必须在$project中明确指定包含项。
  • If you specify an inclusion of a field that does not exist in the document, $project ignores that field inclusion and does not add the field to the document.如果指定包含文档中不存在的字段,$project将忽略该字段包含,并且不会将该字段添加到文档中。

Suppress the _id Field抑制_id字段

By default, the _id field is included in the output documents. 默认情况下,_id字段包含在输出文档中。To exclude the _id field from the output documents, you must explicitly specify the suppression of the _id field in $project.要从输出文档中排除_id字段,必须在$project中明确指定对_id字段的抑制。

Exclude Fields排除字段

New in version 3.4.版本3.4中的新功能。

If you specify the exclusion of a field or fields, all other fields are returned in the output documents.如果指定排除一个或多个字段,则输出文档中将返回所有其他字段。

{ $project: { "<field1>": 0, "<field2>": 0, ... } } // Return all but the specified fields返回除指定字段外的所有字段

If you specify the exclusion of a field other than _id, you cannot employ any other $project specification forms: i.e. if you exclude fields, you cannot also specify the inclusion of fields, reset the value of existing fields, or add new fields. 如果指定排除_id以外的字段,则不能使用任何其他$project规范表单:即,如果排除字段,则也不能指定包含字段、重置现有字段的值或添加新字段。This restriction does not apply to conditional exclusion of a field using the REMOVE variable.此限制不适用于使用REMOVE变量的字段的条件排除。

See also the $unset stage to exclude fields.另请参见$unset阶段以排除字段。

Exclude Fields Conditionally有条件地排除字段

New in version 3.6.版本3.6中的新功能。

Starting in MongoDB 3.6, you can use the variable REMOVE in aggregation expressions to conditionally suppress a field. 从MongoDB 3.6开始,可以在聚合表达式中使用变量REMOVE有条件地抑制字段。For an example, see Conditionally Exclude Fields.有关示例,请参阅条件排除字段

Add New Fields or Reset Existing Fields添加新字段或重置现有字段

Note

MongoDB also provides $addFields to add new fields to the documents.MongoDB还提供$addFields来向文档添加新字段。

To add a new field or to reset the value of an existing field, specify the field name and set its value to some expression. 要添加新字段或重置现有字段的值,请指定字段名称并将其值设置为某个表达式。For more information on expressions, see Expressions.有关表达式的详细信息,请参阅表达式

Literal Values文字值

To set a field value directly to a numeric or boolean literal, as opposed to setting the field to an expression that resolves to a literal, use the $literal operator. 要将字段值直接设置为数值或布尔文字,而不是将字段设置为解析为文字的表达式,请使用$literal运算符。Otherwise, $project treats the numeric or boolean literal as a flag for including or excluding the field.否则,$project将数字或布尔文字视为包含或排除字段的标志。

Field Rename字段重命名

By specifying a new field and setting its value to the field path of an existing field, you can effectively rename a field.通过指定新字段并将其值设置为现有字段的字段路径,可以有效地重命名字段。

New Array Fields新数组字段

Starting in MongoDB 3.2, $project stage supports using the square brackets [] to directly create new array fields. 从MongoDB 3.2开始,$project阶段支持使用方括号[]直接创建新的数组字段。If array specification includes fields that are non-existent in a document, the operation substitutes null as the value for that field. 如果数组规范包含文档中不存在的字段,则该操作会将null替换为该字段的值。For an example, see Project New Array Fields.有关示例,请参阅投影新数组字段

Embedded Document Fields嵌入的文档字段

When projecting or adding/resetting a field within an embedded document, you can either use dot notation, as in在嵌入文档中投影或添加/重置字段时,可以使用点表示法,如中所示

"contact.address.country": <1 or 0 or expression>

Or you can nest the fields:也可以嵌套字段:

contact: { address: { country: <1 or 0 or expression> } }

When nesting the fields, you cannot use dot notation inside the embedded document to specify the field, e.g. contact: { "address.country": <1 or 0 or expression> } is invalid.嵌套字段时,不能在嵌入文档中使用点符号指定字段,例如,contact: { "address.country": <1 or 0 or expression> }无效。

Path Collision Errors in Embedded Fields嵌入字段中的路径冲突错误

You cannot specify both an embedded document and a field within that embedded document in the same projection.不能在同一投影中同时指定嵌入文档和该嵌入文档中的字段。

The following $project stage fails with a Path collision error because it attempts to project both the embedded contact document and the contact.address.country field:以下$project阶段失败,出现路径冲突错误,因为它试图投影嵌入的contact文档和contact.address.country字段:

{ $project: { contact: 1, "contact.address.country": 1 } }

The error occurs regardless of the order in which the parent document and embedded field are specified. 无论父文档和嵌入字段的指定顺序如何,都会发生此错误。The following $project fails with the same error:以下$project失败,并出现相同错误:

{ $project: { "contact.address.country": 1, contact: 1 } }

Restrictions局限性

Changed in version 3.4.在版本3.4中更改。

MongoDB 3.4 and later produces an error if the $project specification is an empty document.如果$project规范是空文档,MongoDB 3.4及更高版本会产生错误。

Examples示例

Include Specific Fields in Output Documents在输出文档中包括特定字段

Consider a books collection with the following document:考虑一个books集合,有以下文档:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5
}

The following $project stage includes only the _id, title, and the author fields in its output documents:以下$project阶段在其输出文档中仅包括_idtitleauthor字段:

db.books.aggregate( [ { $project : { title : 1 , author : 1 } } ] )

The operation results in the following document:操作结果如下所示:

{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }

Suppress _id Field in the Output Documents在输出文档中抑制_id字段

The _id field is always included by default. 默认情况下,始终包括_id字段。To exclude the _id field from the output documents of the $project stage, specify the exclusion of the _id field by setting it to 0 in the projection document.要从$project阶段的输出文档中排除_id字段,请通过在投影文档中将_id字段设置为0来指定排除_id字段。

Consider a books collection with the following document:考虑一个books集合,有以下文档:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5
}

The following $project stage excludes the _id field but includes the title, and the author fields in its output documents:以下$project阶段不包括_id字段,但在其输出文档中包括titleauthor字段:

db.books.aggregate( [ { $project : { _id: 0, title : 1 , author : 1 } } ] )

The operation results in the following document:操作结果如下所示:

{ "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }

Exclude Fields from Output Documents从输出文档中排除字段

New in version 3.4.版本3.4中的新功能。

Consider a books collection with the following document:考虑一个books集合,有以下文档:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5,
  lastModified: "2016-07-28"
}

The following $project stage excludes the lastModified field from the output:以下$project阶段将lastModified字段从输出中排除:

db.books.aggregate( [ { $project : { "lastModified": 0 } } ] )

See also the $unset stage to exclude fields.另请参见$unset阶段以排除字段。

Exclude Fields from Embedded Documents从嵌入文档中排除字段

New in version 3.4.版本3.4中的新功能。

Consider a books collection with the following document:考虑一个books集合,有以下文档:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5,
  lastModified: "2016-07-28"
}

The following $project stage excludes the author.first and lastModified fields from the output:以下$project阶段从输出中排除author.firstlastModified字段:

db.books.aggregate( [ { $project : { "author.first" : 0, "lastModified" : 0 } } ] )

Alternatively, you can nest the exclusion specification in a document:或者,您可以在文档中嵌套排除规范:

db.bookmarks.aggregate( [ { $project: { "author": { "first": 0}, "lastModified" : 0 } } ] )

Both specifications result in the same output:两种规格产生相同的输出:

{
   "_id" : 1,
   "title" : "abc123",
   "isbn" : "0001122223334",
   "author" : {
      "last" : "zzz"
   },
   "copies" : 5,
}

See also the $unset stage to exclude fields.另请参见$unset阶段以排除字段。

Conditionally Exclude Fields有条件排除字段

New in version 3.6.版本3.6中的新功能。

Starting in MongoDB 3.6, you can use the variable REMOVE in aggregation expressions to conditionally suppress a field.从MongoDB 3.6开始,可以在聚合表达式中使用变量REMOVE有条件地抑制字段。

Consider a books collection with the following document:考虑一个books集合,有以下文档:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5,
  lastModified: "2016-07-28"
}
{
  "_id" : 2,
  title: "Baked Goods",
  isbn: "9999999999999",
  author: { last: "xyz", first: "abc", middle: "" },
  copies: 2,
  lastModified: "2017-07-21"
}
{
  "_id" : 3,
  title: "Ice Cream Cakes",
  isbn: "8888888888888",
  author: { last: "xyz", first: "abc", middle: "mmm" },
  copies: 5,
  lastModified: "2017-07-22"
}

The following $project stage uses the REMOVE variable to excludes the author.middle field only if it equals "":以下$project阶段仅在其等于""时使用REMOVE变量排除author.middle字段:

db.books.aggregate( [
   {
      $project: {
         title: 1,
         "author.first": 1,
         "author.last" : 1,
         "author.middle": {
            $cond: {
               if: { $eq: [ "", "$author.middle" ] },
               then: "$$REMOVE",
               else: "$author.middle"
            }
         }
      }
   }
] )

The aggregation operation results in the following output:聚合操作将产生以下输出:

{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
{ "_id" : 2, "title" : "Baked Goods", "author" : { "last" : "xyz", "first" : "abc" } }
{ "_id" : 3, "title" : "Ice Cream Cakes", "author" : { "last" : "xyz", "first" : "abc", "middle" : "mmm" } }

Include Specific Fields from Embedded Documents包含嵌入文档中的特定字段

Consider a bookmarks collection with the following documents:使用以下文档考虑bookmarks集合:

{ _id: 1, user: "1234", stop: { title: "book1", author: "xyz", page: 32 } }
{ _id: 2, user: "7890", stop: [ { title: "book2", author: "abc", page: 5 }, { title: "book3", author: "ijk", page: 100 } ] }

To include only the title field in the embedded document in the stop field, you can use the dot notation:要在stop字段中仅包含嵌入文档中的title字段,可以使用点表示法

db.bookmarks.aggregate( [ { $project: { "stop.title": 1 } } ] )

Or, you can nest the inclusion specification in a document:或者,您可以在文档中嵌套包含规范:

db.bookmarks.aggregate( [ { $project: { stop: { title: 1 } } } ] )

Both specifications result in the following documents:这两个规范产生了以下文件:

{ "_id" : 1, "stop" : { "title" : "book1" } }
{ "_id" : 2, "stop" : [ { "title" : "book2" }, { "title" : "book3" } ] }

Include Computed Fields包括计算字段

Consider a books collection with the following document:考虑一个books集合,有以下文档:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5
}

The following $project stage adds the new fields isbn, lastName, and copiesSold:以下$project阶段添加了新字段isbnlastNamecopiesSold

db.books.aggregate(
   [
      {
         $project: {
            title: 1,
            isbn: {
               prefix: { $substr: [ "$isbn", 0, 3 ] },
               group: { $substr: [ "$isbn", 3, 2 ] },
               publisher: { $substr: [ "$isbn", 5, 4 ] },
               title: { $substr: [ "$isbn", 9, 3 ] },
               checkDigit: { $substr: [ "$isbn", 12, 1] }
            },
            lastName: "$author.last",
            copiesSold: "$copies"
         }
      }
   ]
)

The operation results in the following document:操作结果如下所示:

{
   "_id" : 1,
   "title" : "abc123",
   "isbn" : {
      "prefix" : "000",
      "group" : "11",
      "publisher" : "2222",
      "title" : "333",
      "checkDigit" : "4"
   },
   "lastName" : "zzz",
   "copiesSold" : 5
}

Project New Array Fields投影新数组字段

For example, if a collection includes the following document:例如,如果集合包含以下文档:

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "x" : 1, "y" : 1 }

The following operation projects the fields x and y as elements in a new field myArray:以下操作将字段xy投影为新字段myArray中的元素:

db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y" ] } } ] )

The operation returns the following document:该操作将返回以下文档:

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1 ] }

If array specification includes fields that are non-existent in a document, the operation substitutes null as the value for that field.如果数组规范包含文档中不存在的字段,则该操作会将null替换为该字段的值。

For example, given the same document as above, the following operation projects the fields x, y, and a non-existing field $someField as elements in a new field myArray:例如,给定与上述相同的文档,以下操作将字段xy和不存在的字段$someField投影为新字段myArray中的元素:

db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y", "$someField" ] } } ] )

The operation returns the following document:该操作将返回以下文档:

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1, null ] }