On this page
$project (aggregation)
在本页面
Definition
$project
- 将带有请求字段的文档传递到管道的下一个阶段。指定的字段可以是 Importing 文档中的现有字段,也可以是新计算的字段。
$project阶段具有以下原型形式:
{ $project: { <specification(s)> } }
$project可以使用一个文档,该文档可以指定字段的包含,_id
字段的禁止显示,新字段的添加以及现有字段的值的重置。或者,您可以指定字段的“排除”。
$project规范具有以下形式:
Form | Description |
---|---|
<field>: <1 or true> |
指定包含一个字段。 |
_id: <0 or false> |
指定对_id 字段的抑制。 |
要有条件地排除字段,请改用REMOVE变量。有关详细信息,请参见有条件地排除字段。
| <field>: <expression>
|添加新字段或重置现有字段的值。
在版本 3.6 中进行了更改:MongoDB 3.6 添加了变量REMOVE。如果表达式的计算结果为$$REMOVE
,则该字段将排除在输出中。有关详细信息,请参见有条件地排除字段。
| <field>:<0 or false>
|版本 3.4 中的新功能。
指定排除字段。
要有条件地排除字段,请改用REMOVE变量。有关详细信息,请参见有条件地排除字段。
如果您指定了_id
以外的其他字段,则您不能**使用其他任何$project规格表。此限制不适用于使用REMOVE变量有条件地排除字段。
Considerations
包含现有字段
默认情况下,
_id
字段包含在输出文档中。要将 Importing 文档中的任何其他字段包括在输出文档中,必须在$project中明确指定包含。如果您指定包含文档中不存在的字段,则$project会忽略该字段包含并且不会将字段添加到文档中。
禁止_id 字段
默认情况下,_id
字段包含在输出文档中。要从输出文档中排除_id
字段,必须在$project中显式指定对_id
字段的禁止。
Exclude Fields
3.4 版的新功能。
如果指定一个或多个字段排除,则所有其他字段将在输出文档中返回。
如果您指定排除_id
以外的其他字段,则不能使用任何其他$project规格形式:即,如果您排除字段,则也不能指定包含字段,重置现有字段的值或添加新字段。此限制不适用于使用REMOVE变量有条件地排除字段。
有条件排除字段
3.6 版的新功能。
从 MongoDB 3.6 开始,您可以在聚合表达式中使用变量REMOVE来有条件地禁止显示字段。有关示例,请参见有条件地排除字段。
添加新字段或重置现有字段
Note
MongoDB 还提供$addFields将新字段添加到文档中。
要添加新字段或重置现有字段的值,请指定字段名称并将其值设置为某些表达式。有关表达式的更多信息,请参见Expressions。
Literal Values
要将字段值直接设置为数字或布尔 Literals,而不是将字段设置为可解析为 Literals 的表达式,请使用$literal运算符。否则,$project将数字或布尔 Literals 视为包含或排除该字段的标志。
Field Rename
通过指定新字段并将其值设置为现有字段的字段路径,可以有效地重命名字段。
新数组字段
从 MongoDB 3.2 开始,$project阶段支持使用方括号[]
直接创建新的数组字段。如果数组规范包含文档中不存在的字段,则该操作将null
替换为该字段的值。有关示例,请参见投影新的数组字段。
嵌入式文档字段
在嵌入式文档中投影或添加/重置字段时,可以使用dot notation,如
"contact.address.country": <1 or 0 or expression>
或者,您可以嵌套字段:
contact: { address: { country: <1 or 0 or expression> } }
嵌套字段时,不能在嵌入式文档中使用点符号来指定字段,例如contact: { "address.country": <1 or 0 or expression> }
是无效。
Restrictions
在版本 3.4 中更改。
如果$project规范为空文档,则 MongoDB 3.4 及更高版本会产生错误。
Examples
在输出文档中包括特定字段
考虑包含以下文档的books
集合:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}
以下$project阶段在其输出文档中仅包含_id
,title
和author
字段:
db.books.aggregate( [ { $project : { title : 1 , author : 1 } } ] )
该操作产生以下文档:
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
禁止输出文档中的_id 字段
默认情况下始终包含_id
字段。要从$project阶段的输出文档中排除_id
字段,请通过在投影文档中将_id
字段设置为0
来指定排除。
考虑包含以下文档的books
集合:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}
以下$project阶段在其输出文档中不包括_id
字段,但包括title
和author
字段:
db.books.aggregate( [ { $project : { _id: 0, title : 1 , author : 1 } } ] )
该操作产生以下文档:
{ "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
从输出文档中排除字段
3.4 版的新功能。
考虑包含以下文档的books
集合:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5,
lastModified: "2016-07-28"
}
以下$project阶段从输出中排除lastModified
字段:
db.books.aggregate( [ { $project : { "lastModified": 0 } } ] )
从嵌入式文档中排除字段
3.4 版的新功能。
考虑包含以下文档的books
集合:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5,
lastModified: "2016-07-28"
}
以下$project阶段从输出中排除author.first
和lastModified
字段:
db.books.aggregate( [ { $project : { "author.first" : 0, "lastModified" : 0 } } ] )
或者,您可以将排除规范嵌套在文档中:
db.bookmarks.aggregate( [ { $project: { "author": { "first": 0}, "lastModified" : 0 } } ] )
两种规格的结果相同:
{
"_id" : 1,
"title" : "abc123",
"isbn" : "0001122223334",
"author" : {
"last" : "zzz"
},
"copies" : 5,
}
有条件排除字段
3.6 版的新功能。
从 MongoDB 3.6 开始,您可以在聚合表达式中使用变量REMOVE来有条件地禁止显示字段。
考虑包含以下文档的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"
}
以下$project阶段仅在author.middle
等于""
时使用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"
}
}
}
}
] )
聚合操作将产生以下输出:
{ "_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" } }
包括嵌入式文档中的特定字段
考虑包含以下文档的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 } ] }
要在stop
字段的嵌入文档中仅包含title
字段,可以使用dot notation:
db.bookmarks.aggregate( [ { $project: { "stop.title": 1 } } ] )
或者,您可以将包含规范嵌套在文档中:
db.bookmarks.aggregate( [ { $project: { stop: { title: 1 } } } ] )
两种规格均产生以下文件:
{ "_id" : 1, "stop" : { "title" : "book1" } }
{ "_id" : 2, "stop" : [ { "title" : "book2" }, { "title" : "book3" } ] }
包含计算字段
考虑包含以下文档的books
集合:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}
以下$project阶段添加了新字段isbn
,lastName
和copiesSold
:
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"
}
}
]
)
该操作产生以下文档:
{
"_id" : 1,
"title" : "abc123",
"isbn" : {
"prefix" : "000",
"group" : "11",
"publisher" : "2222",
"title" : "333",
"checkDigit" : "4"
},
"lastName" : "zzz",
"copiesSold" : 5
}
投影新的数组字段
例如,如果一个集合包含以下文档:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "x" : 1, "y" : 1 }
以下操作将字段x
和y
投影为新字段myArray
中的元素:
db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y" ] } } ] )
该操作返回以下文档:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1 ] }
如果数组规范包含文档中不存在的字段,则该操作将null
替换为该字段的值。
例如,给定与上述相同的文档,以下操作将字段x
,y
和不存在的字段$someField
投影为新字段myArray
中的元素:
db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y", "$someField" ] } } ] )
该操作返回以下文档:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1, null ] }
See also