Database Manual / Reference / Query Language / Aggregation Stages

$project (aggregation stage)(聚合阶段)

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.将带有请求字段的文档传递到流程的下一阶段。指定的字段可以是输入文档中的现有字段或新计算的字段。

Compatibility兼容性

You can use $project for deployments hosted in the following environments:您可以将$project用于在以下环境中托管的部署:

  • MongoDB Atlas: The fully managed service for MongoDB deployments in the cloud:云中MongoDB部署的完全托管服务
  • MongoDB Enterprise: The subscription-based, self-managed version of MongoDB:MongoDB的基于订阅的自我管理版本
  • MongoDB Community: The source-available, free-to-use, and self-managed version of MongoDB:MongoDB的源代码可用、免费使用和自我管理版本

Syntax语法

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. Alternatively, you may specify the exclusion of fields.$project接受一个文档,该文档可以指定字段的包含、_id字段的抑制、新字段的添加以及现有字段值的重置。或者,您可以指定排除字段。

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

Form形式Description描述
<field>: <1 or true>Specifies the inclusion of a field. Non-zero integers are also treated as true.指定是否包含字段。非零整数也被视为真。
_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.添加新字段或重置现有字段的值。

If the expression evaluates to $$REMOVE, the field is excluded in the output. For details, see Exclude Fields Conditionally.如果表达式的计算结果为$$REMOVE,则该字段将被排除在输出之外。有关详细信息,请参阅有条件排除字段

<field>: <0 or false>

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

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

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阶段以排除字段。

Behavior行为

Include Fields包括字段

  • The _id field is, by default, included in the output documents. To include any other fields from the input documents in the output documents, you must explicitly specify the inclusion in $project.默认情况下,_id字段包含在输出文档中。要将输入文档中的任何其他字段包含在输出文档中,您必须在$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将忽略该字段包含,并且不会将该字段添加到文档中。

_id Field字段

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

Exclude Fields排除字段

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. 如果指定排除_id以外的字段,则不能使用任何其他$project规范形式:即。if you exclude fields, you cannot also specify the inclusion of fields, reset the value of existing fields, or add new fields. 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有条件地排除字段

You can use the variable REMOVE in aggregation expressions to conditionally suppress a field. For an example, see Conditionally Exclude Fields.您可以在聚合表达式中使用变量REMOVE来有条件地抑制字段。例如,请参阅有条件排除字段

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新建数组字段

The $project stage supports using the square brackets [] to directly create new array fields. If you specify array fields that do not exist in a document, the operation substitutes null as the value for that field. For an example, see Project New Array Fields.$project阶段支持使用方括号[]直接创建新的数组字段。如果指定文档中不存在的数组字段,则操作将用null替换该字段的值。例如,请参阅项目新数组字段。

You cannot use an array index with the $project stage. For more information, see Array Indexes are Unsupported.您不能在$project阶段使用数组索引。有关详细信息,请参阅不支持数组索引

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

$project Stage Placement阶段布置

When you use a $project stage it should typically be the last stage in your pipeline, used to specify which fields to return to the client.当您使用$project阶段时,它通常应该是管道中的最后一个阶段,用于指定要返回给客户端的字段。

Using a $project stage at the beginning or middle of a pipeline to reduce the number of fields passed to subsequent pipeline stages is unlikely to improve performance, because the database performs this optimization automatically.在管道的开始或中间使用$project阶段来减少传递给后续管道阶段的字段数量不太可能提高性能,因为数据库会自动执行此优化。

Considerations注意事项

Empty Specification空白规格

MongoDB returns an error if the $project stage is passed an empty document.如果向$project阶段传递了一个空文档,MongoDB将返回错误。

For example, running the following pipeline produces an error:例如,运行以下管道会产生错误:

db.myCollection.aggregate( [ {
$project: { }
} ] )

Array Index数组索引

You cannot use an array index with the $project stage. For more information, see Array Indexes are Unsupported.您不能在$project阶段使用数组索引。有关详细信息,请参阅不支持数组索引

Examples示例

MongoDB Shell

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. 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.默认情况下,_id字段始终包含在内。要从$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从输出文档中排除字段

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从嵌入文档中排除字段

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有条件地排除字段

You can use the variable REMOVE in aggregation expressions to conditionally suppress a field.您可以在聚合表达式中使用变量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阶段仅在author.middle字段等于""时使用REMOVE变量排除该字段:

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

Tip

Comparison with $addFields$addFields的比较

You can use either the $addFields or $project stage to remove document fields. The best approach depends on your pipeline and how much of the original document you want to retain.您可以使用$addFields$project阶段删除文档字段。最佳方法取决于您的管道以及您希望保留多少原始文档。

To see an example using $$REMOVE in an $addFields stage, see Remove Fields.要查看在$addFields阶段使用$$REMOVE的示例,请参阅删除字段

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

Array Indexes are Unsupported不支持数组索引

You cannot use an array index with the $project stage. This section shows an example.您不能在$project阶段使用数组索引。本节显示了一个示例。

Create the following pizzas collection:创建以下pizzas集合:

db.pizzas.insert( [
{ _id: 0, name: [ 'Pepperoni' ] },
] )

The following example returns the pizza:以下示例返回披萨:

db.pizzas.aggregate( [
{ $project: { x: '$name', _id: 0 } },
] )

The pizza is returned in the example output:披萨在示例输出中返回:

[ { x: [ 'Pepperoni' ] } ]

The following example uses an array index ($name.0) to attempt to return the pizza:以下示例使用数组索引($name.0)尝试返回披萨:

db.pizzas.aggregate( [
{ $project: { x: '$name.0', _id: 0 } },
] )

The pizza is not returned in the example output:示例输出中没有返回披萨:

[ { x: [] } ]
C#

The C# examples on this page use the sample_mflix database from the Atlas sample datasets. 本页上的C#示例使用Atlas示例数据集中的sample_mflix数据库。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB .NET/C# Driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB .NET/C#驱动程序文档中的入门

The following Movie and ImdbData classes model the documents in the sample_mflix.movies collection:以下MovieImdbData类对sample_mflix.movies集合中的文档进行建模:

public class Movie
{
public ObjectId Id { get; set; }

public string Title { get; set; }

public List<string> Genres { get; set; }

public List<string> Directors { get; set; }

public List<string> Writers { get; set; }

public string Type { get; set; }

public string Plot { get; set; }

public ImdbData Imdb { get; set; }

public List<string> Cast { get; set; }
}
public class ImdbData
{
public string Id { get; set; }

public int Votes { get; set; }

public float Rating { get; set; }
}

Note

ConventionPack for Pascal CasePascal大小写的约定包

The C# classes on this page use Pascal case for their property names, but the field names in the MongoDB collection use camel case. To account for this difference, you can use the following code to register a ConventionPack when your application starts:此页面上的C#类使用Pascal大小写作为其属性名,但MongoDB集合中的字段名使用驼峰大小写。为了解释这种差异,您可以在应用程序启动时使用以下代码注册ConventionPack

var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);

To use the MongoDB .NET/C# driver to add a $project stage to an aggregation pipeline, call the Project() method on a PipelineDefinition object and pass a ProjectionDefinitionBuilder<TDocument> object. 要使用MongoDB .NET/C#驱动程序将$project阶段添加到聚合管道中,请在PipelineDefinition对象上调用project()方法,并传递ProjectionDefinitionBuilder<TDocument>对象。TDocument is the class that represents the documents in your collection.是表示集合中文档的类。

The following sections show the different ways that you can customize the output documents of the $project stage.以下部分显示了自定义$project阶段输出文档的不同方法。

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

To include specific fields when using the .NET/C# driver, call the Include() method on the projection builder. You can chain Include() calls to include multiple fields.要在使用.NET/C#驱动程序时包含特定字段,请在投影生成器上调用include()方法。您可以链接Include()调用以包含多个字段。

The following code example produces a document that includes only the _id, plot, and title fields:以下代码示例生成了一个仅包含_idplottitle字段的文档:

var pipeline = new EmptyPipelineDefinition<Movie> ()
.Project(
Builders<Movie>.Projection
.Include(m => m.Title)
.Include(m => m.Plot)
);

var result = movieCollection.Aggregate(pipeline).FirstOrDefault();

The pipeline returns the following document:管道返回以下文档:

{
"_id" : { "$oid" : "573a1390f29313caabcd42e8" },
"plot" : "A group of bandits stage a brazen train hold-up, only to find a
determined posse hot on their heels.",
"title" : "The Great Train Robbery"
}

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

To exclude a field from the result documents when using the .NET/C# driver, call the Exclude() method on the projection builder. You can chain Exclude() calls to exclude multiple fields.要在使用NET/C#驱动程序时从结果文档中排除字段,请在投影生成器上调用exclude()方法。您可以链接Exclude()调用以排除多个字段。

The following code example produces a document that excludes the Type field:以下代码示例生成了一个不包含Type字段的文档:

var pipeline = new EmptyPipelineDefinition<Movie>()
.Project(
Builders<Movie>.Projection
.Exclude(m => m.Type)
);

var result = movieCollection.Aggregate(pipeline).FirstOrDefault();

By default, result documents always include the _id field. The following code example produces a document that excludes the _id field but includes the plot and title fields:默认情况下,结果文档始终包含_id字段。以下代码示例生成一个文档,该文档不包括_id字段,但包括plottitle字段:

var pipeline = new EmptyPipelineDefinition<Movie> ()
.Project(
Builders<Movie>.Projection
.Exclude(m => m.Id)
.Include(m => m.Title)
.Include(m => m.Plot)
);

var result = movieCollection.Aggregate(pipeline).FirstOrDefault();

The pipeline results in the following document:该管道产生以下文件:

{
"plot" : "A group of bandits stage a brazen train hold-up, only to find a
determined posse hot on their heels.",
"title" : "The Great Train Robbery"
}

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

To exclude a field in an embedded document when using the .NET/C# driver, call the Exclude() method on the projection builder and pass the path to the corresponding class property. You can chain Exclude() calls to exclude multiple fields.要在使用.NET/C#驱动程序时排除嵌入式文档中的字段,请调用投影生成器上的Exclude()方法,并将路径传递给相应的类属性。您可以链接Exclude()调用以排除多个字段。

The following code example produces a document that excludes the imdb.id and type fields:以下代码示例生成了一个不包括imdb.idtype字段的文档:

var pipeline = new EmptyPipelineDefinition<Movie> ()
.Project(
Builders<Movie>.Projection
.Exclude("Imdb.id")
.Exclude(m => m.Type)
);

var result = movieCollection.Aggregate(pipeline).FirstOrDefault();

The pipeline results in the following output:管道产生以下输出:

{
"plot" : "A group of bandits stage a brazen train hold-up, only to find a
determined posse hot on their heels.",
"title" : "The Great Train Robbery",
...
"imdb" : { "rating" : 7.4000000000000004, "votes" : 9847 }
}

Note

Use Strings for Embedded ID Fields将字符串用于嵌入式ID字段

To project an ID field in an embedded document, specify the field name as a string, not a lambda expression.要在嵌入式文档中投影ID字段,请将字段名指定为字符串,而不是lambda表达式。

Conditionally Exclude Fields有条件地排除字段

You can use the variable REMOVE in aggregation expressions to conditionally suppress a field:您可以在聚合表达式中使用变量REMOVE来有条件地抑制字段:

var stage = new BsonDocument
{
{ "title", 1 },
{ "imdb.id", 1 },
{ "imdb.rating", 1 },
{
"imdb.votes", new BsonDocument("$cond", new BsonDocument
{
{ "if", new BsonDocument("$eq", new BsonArray { "", "$imdb.votes" }) },
{ "then", "$$REMOVE" },
{ "else", "$imdb.votes" }
})
}
};

var pipeline = new EmptyPipelineDefinition<Movie>()
.Project(stage)
.Sample(1);

var result = movieCollection.Aggregate(pipeline).FirstOrDefault();

Note

No Builder for Conditional Exclusion无建筑商可进行条件排除

The preceding example uses BsonDocument objects because the .NET/C# driver doesn't provide a builder to conditionally exclude fields. 前面的示例使用BsonDocument对象,因为NET/C#驱动程序没有提供有条件地排除字段的构建器。Other MongoDB language drivers might support this feature. See the MongoDB driver documentation for more information.其他MongoDB语言驱动程序可能支持此功能。有关更多信息,请参阅MongoDB驱动程序文档

If the sampled document contains the imdb.votes field, the pipeline returns a document similar to the following:如果采样文档包含imdb.votes字段,则管道将返回类似于以下内容的文档:

{
"_id" : { "$oid" : "573a1390f29313caabcd42e8" },
"title" : "The Great Train Robbery",
"imdb" : { "rating" : 7.4000000000000004, "id" : 439, "votes" : 9847 }
}

If the document doesn't contain the imdb.votes field, the pipeline returns a document similar to the following:如果文档不包含imdb.votes字段,则管道将返回类似于以下内容的文档:

{
"_id" : { "$oid" : "573a1398f29313caabce94a3" },
"title" : "This Is Spinal Tap",
"imdb" : { "rating" : 8.0, "id" : 88258 }
}

Include Computed Fields包括计算字段

To include computed fields in the result documents when using the .NET/C# driver, call the Expression() method on the projection builder and pass an expression that includes the computed fields. 要在使用.NET/C#驱动程序时在结果文档中包含计算字段,请调用投影生成器上的Expression()方法,并传递一个包含计算字段的表达式。For added type safety, you can define a model class for the result documents, like the following ProjectedMovie class:为了增加类型安全性,您可以为结果文档定义一个模型类,如以下ProjectedMovie类:

public class ProjectedMovie
{
public ObjectId Id { get; set; }

public string Title { get; set; }

public string LeadActor { get; set; }

public List<string> Crew { get; set; }
}

The following code example produces a document that includes multiple computed fields:以下代码示例生成了一个包含多个计算字段的文档:

var pipeline = new EmptyPipelineDefinition<Movie>()
.Project(
Builders<Movie>
.Projection
.Expression(m => new ProjectedMovie
{
Id = m.Id,
Title = m.Title,
LeadActor = m.Cast[0],
})
);

var result = movieCollection.Aggregate(pipeline).FirstOrDefault();

The pipeline results in the following document:该管道产生以下文件:

{
"_id" : { "$oid" : "573a1390f29313caabcd42e8" },
"title" : "The Great Train Robbery",
"leadActor" : "A.C. Abadie",
...
}

Project New Array Fields项目新数组字段

To project new array fields in the result documents when using the .NET/C# driver, call the Expression() method on the projection builder and pass an expression that includes the new array fields. 要在使用NET/C#驱动程序时在结果文档中投影新的数组字段,请在投影生成器上调用Expression()方法,并传递一个包含新数组字段的表达式。For added type safety, you can define a model class for the result documents, like the following ProjectedMovie class:为了增加类型安全性,您可以为结果文档定义一个模型类,如以下ProjectedMovie类:

public class ProjectedMovie
{
public ObjectId Id { get; set; }

public string Title { get; set; }

public string LeadActor { get; set; }

public List<string> Crew { get; set; }
}

The following code example produces documents that include a new array field, crew, which contains values from the directors and writers fields:以下代码示例生成的文档包含一个新的数组字段crew,其中包含directorswriter字段中的值:

var pipeline = new EmptyPipelineDefinition<Movie> ()
.Project(
Builders<Movie>
.Projection
.Expression(m => new ProjectedMovie
{
Id = m.Id,
Title = m.Title,
LeadActor = m.Cast[0],
Crew = m.Directors.Concat(m.Writers).ToList()
}
)
)
.Sample(1);

var result = movieCollection.Aggregate(pipeline).FirstOrDefault();

The pipeline returns a document similar to the following:管道返回一个类似于以下内容的文档:

{
"_id" : { "$oid" : "573a1395f29313caabce2297" },
"title" : "The Chalk Garden",
"leadActor" : "Deborah Kerr",
"crew" : ["Ronald Neame", "John Michael Hayes (screenplay)", "Enid Bagnold (from the play by)"]
}

If the array specification includes fields that are non-existent in a document, the pipeline substitutes null as the value for that field. 如果数组规范包含文档中不存在的字段,则管道会将null替换为该字段的值。For example, the following code example projects the fields directors, writers, and a non-existent field, makeupArtists, as elements in a new field named crew:例如,以下代码示例将字段directorswriter和不存在的字段makeupArtists作为元素投影到名为crew的新字段中:

var stage = new BsonDocument
{
{ "crew", new BsonArray { "$directors", "$writers", "$makeupArtists" } }
};

var pipeline = new EmptyPipelineDefinition<Movie>()
.Project(stage)
.Sample(1);
var result = movieCollection.Aggregate(pipeline).FirstOrDefault();

The pipeline returns a document similar to the following:管道返回一个类似于以下内容的文档:

{
"_id" : { "$oid" : "573a1399f29313caabced0d9" },
"crew" : [["Bill Kroyer"], ["Jim Cox (screenplay)", "Diana Young (original stories)"], null]
}

Note

Builders Class Prevents Missing FieldsBuilders类防止丢失字段

The preceding example uses BsonDocument objects because the .NET/C# driver raises a compile-time error if you try to use builders to add a missing field to an array. Other MongoDB language drivers might support this feature. 前面的示例使用BsonDocument对象,因为如果您尝试使用构建器向数组添加缺少的字段,NET/C#驱动程序会引发编译时错误。其他MongoDB语言驱动程序可能支持此功能。See the MongoDB driver documentation for more information.有关更多信息,请参阅MongoDB驱动程序文档

Node.js

The Node.js examples on this page use the sample_mflix database from the Atlas sample datasets. 本页上的Node.js示例使用Atlas示例数据集中的sample_mflix数据库。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB Node.js driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB Node.js驱动程序文档中的入门

To use the MongoDB Node.js driver to add a $project stage to an aggregation pipeline, use the $project operator in a pipeline object.要使用MongoDB Node.js驱动程序向聚合管道添加$project阶段,请在管道对象中使用$project运算符。

The following sections show how to customize the output documents of the $project stage.以下部分显示了如何自定义$project阶段的输出文档。

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

To include specific fields, set the value of the field to 1 in the $project stage.要包含特定字段,请在$project阶段将字段的值设置为1

The following example returns documents that include only the _id, plot, and title fields:以下示例返回仅包含_idplottitle字段的文档:

const pipeline = [
{
$project: {
title: 1,
plot: 1
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

The output documents resemble the following example:输出文档类似于以下示例:

{
_id: new ObjectId('573a1390f29313caabcd42e8'),
plot: 'A group of bandits stage a brazen train hold-up, only to find a
determined posse hot on their heels.',
title: 'The Great Train Robbery'
}

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

To exclude specific fields, set the value of the field to 0 in the $project stage.要排除特定字段,请在$project阶段将字段的值设置为0

The following example returns documents that exclude the type field:以下示例返回不包含type字段的文档:

const pipeline = [
{
$project: {
type: 0
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

By default, result documents always include the _id field. The following example returns documents that exclude the _id field but include the plot and title fields:默认情况下,结果文档始终包含_id字段。以下示例返回不包括_id字段但包括plottitle字段的文档:

const pipeline = [
{
$project: {
_id: 0,
title: 1,
plot: 1
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

The output documents resemble the following example:输出文档类似于以下示例:

{
plot: 'A group of bandits stage a brazen train hold-up, only to find a
determined posse hot on their heels.',
title: 'The Great Train Robbery'
}

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

To exclude a field in an embedded document, set value of the field path to 0 in the $project stage.要排除嵌入文档中的字段,请在$project阶段将字段路径的值设置为0

Note

Use Strings for Embedded Fields将字符串用于嵌入式字段

To project a field in an embedded document, specify the field path as a string.要在嵌入式文档中投影字段,请将字段路径指定为字符串。

The following example returns documents that exclude the imdb.id and type fields:以下示例返回不包括imdb.idtype字段的文档:

const pipeline = [
{
$project: {
"imdb.id": 0,
type: 0
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

The output documents resemble the following example:输出文档类似于以下示例:

{
plot: 'A group of bandits stage a brazen train hold-up, only to find a
determined posse hot on their heels.',
title: 'The Great Train Robbery',
imdb: { rating: 7.4000000000000004, votes: 9847 }
}

Conditionally Exclude Fields有条件地排除字段

To conditionally exclude a field, assign conditional logic that includes the variable REMOVE to the field name.要有条件地排除字段,请将包含变量REMOVE的条件逻辑分配给字段名。

const pipeline = [
{
$project: {
title: 1,
"imdb.id": 1,
"imdb.rating": 1,
"imdb.votes": {
$cond: {
if: { $eq: ["$imdb.votes", ""] },
then: "$REMOVE",
else: "$imdb.votes"
}
}
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

If a document contains the imdb.votes field, the pipeline returns documents that resemble the following example output:如果文档包含imdb.votes字段,则管道将返回类似于以下示例输出的文档:

{
_id: new ObjectId('573a1390f29313caabcd42e8'),
title: 'The Great Train Robbery',
imdb: { rating : 7.4000000000000004, id: 439, votes: 9847 }
}

If a document doesn't contain the imdb.votes field, the pipeline returns documents that resemble the following example output:如果文档不包含imdb.votes字段,管道将返回类似于以下示例输出的文档:

{
_id: new ObjectId('573a1390f29313caabcd42e8'),
title: 'This Is Spinal Tap',
imdb: { rating: 8.0, id: 88258 }
}

Include Computed Fields包括计算字段

To include computed fields in the result documents, assign an expression to the field that stores the results.要在结果文档中包含计算字段,请为存储结果的字段分配一个表达式。

The following example projects the _id and title fields into new fields of the same name and computes the new field leadActor. The example then returns documents that include these fields:以下示例将_idtitle字段投影到同名的新字段中,并计算新字段leadActor。然后,该示例返回包含以下字段的文档:

const pipeline = [
{
$project: {
_id: "$_id",
title: "$title",
leadActor: { $arrayElemAt: ["$cast", 0] }
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

The output documents resemble the following example:输出文档类似于以下示例:

{
_id: new ObjectId('573a1390f29313caabcd42e8'),
title: 'The Great Train Robbery',
leadActor: 'A.C. Abadie'
}

Project New Array Fields项目新数组字段

To project new array fields in the result documents, assign an expression that computes the new array field to the field that stores the array.要在结果文档中投影新的数组字段,请将计算新数组字段的表达式分配给存储数组的字段。

The following example returns documents that include a new array field, crew, which combines values from the directors and writers fields:以下示例返回包含新数组字段crew的文档,该字段组合了directorwriter字段中的值:

const pipeline = [
{
$project: {
_id: "$_id",
title: "$title",
leadActor: { $arrayElemAt: ["$cast", 0] },
crew: { $concatArrays: ["$directors", "$writers"] }
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

The output documents resemble the following example:输出文档类似于以下示例:

{
_id: new ObjectId('573a1395f29313caabce2297'),
title: 'The Chalk Garden',
leadActor: 'Deborah Kerr',
crew: ['Ronald Neame', 'John Michael Hayes (screenplay)', 'Enid Bagnold (from the play by)']
}

If the array specification includes fields that aren't in a document, the pipeline substitutes null as the value for that field. 如果数组规范包含不在文档中的字段,则管道会将null替换为该字段的值。For example, the following example projects the fields directors, writers, and a non-existent field, makeupArtists, as elements in a new field named crew:例如,以下示例将字段directorswriters和不存在的字段makeupArtists作为元素投影到名为crew的新字段中:

const pipeline = [
{
$project: {
crew: ["$directors", "$writers", "$makeupArtists"]
}
}
];

const cursor = collection.aggregate(pipeline);
return cursor;

The output documents resemble the following example:输出文档类似于以下示例:

{
_id: new ObjectId('573a1399f29313caabced0d9'),
crew: [['Bill Kroyer'], ['Jim Cox (screenplay)', 'Diana Young (original stories)'], null]
}

Learn More了解更多

For more information and detailed explanations of common aggregation tasks, see the Complete Aggregation Pipeline Tutorials.有关常见聚合任务的更多信息和详细说明,请参阅完整的聚合管道教程

To learn more about the methods on this page, see the following guides:要了解有关此页面上方法的更多信息,请参阅以下指南: