- Definition 定义
- Considerations 注意事项
- Example 例子
- Include Specific Fields in Output Documents 在输出文档中包含特定字段
- Suppress
_id
Field in the Output Documents 在输出文档中抑制/禁止_id
字段 - Exclude Fields from Output Documents 从输出文档中排除字段
- Exclude Fields from Embedded Documents 从嵌入式文档中排除字段
- Conditionally Exclude Fields 有条件地排除字段
- Include Specific Fields from Embedded Documents 从嵌入式文档中包含指定指端
- Include Computed Fields 包含计算字段
- Project New Array Fields Project 新的数组字段
- Array Indexes are Unspported
- 参考
Definition 定义
将带有请求字段的文档传递给 pipeline 中的下一个 stage。指定的字段可以是
输入文档中的现有字段
或新计算的字段
。
$project stage 具有以下原型形式:
{ $project: { <specificatino(s)> } }
$project 接收一个文档,该文档可以指定包含字段
、禁止 _id 字段
、添加新字段
以及重设现有字段的值
。或者,你也可以指定排除字段
。
$project 规范有以下形式:
Form | Description |
---|---|
<field>: <1 or true> |
指定包含一个字段。非零(non-zero)的整数也被视为 true 。 |
_id: <0 or false> |
指定禁止 _id 字段。要有条件地排除一个字段,请使用 REMOVE 变量来代替。详情参阅 Exclude Fields Conditionally(有条件地排除字段)。 |
<field>: <expression> |
添加新字段或重置现有字段的值。 如果表达式评估为 $$REMOVE ,输出中就会排除该字段。详情参阅 Exclude Fields Conditionally(有条件地排除字段)。 |
<field>: <0 or false> |
指定排除一个字段。 要有条件地排除一个字段,请使用 REMOVE 变量来代替。详情参阅 Exclude Fields Conditionally(有条件地排除字段)。 如果您指定排除 _id 以外的字段,您**不能** 使用任何其他 $project 规范形式。这一限制并不适用于使用 REMOVE 变量有条件地排除一个字段。也可以参阅 $unset stage,以排除字段。 |
Considerations 注意事项
Include Existing Fields 包含现有字段
- 默认情况下,
_id
字段被包含在输出文档中。要在输出文档中包含输入文档中的任何其他字段,你必须在 $project 中明确指定包含。 - 如果你指定包含一个在文档中不存在的字段,$project 会忽略该字段的包含,并且不将该字段添加到文档中。
Suppress the
默认情况下,_id
Field 抑制/禁止_id
字段_id
字段被包含在输出文档中。要从输出文档中排除_id
字段,你必须在 $project 中明确指定抑制/禁止_id
字段。Exclude Fields 排除字段
如果你指定排除一个或多个字段,那么所有其他的字段将在输出文档中返回。
如果您指定排除{ $project: { "<field1>": 0, "<field2>": 0, ... } } // 返回除指定字段之外的所有字段
_id
以外的字段,您不能采用任何其他 $project 规范形式:即如果您排除字段,您也不能指定包含字段,重置现有字段的值,或添加新字段。这一限制并不适用于使用 REMOVE 变量的有条件排除字段。
也可参阅 $unset stage,以排除字段。
Exclude Fields Conditionally 有条件地排除字段
你可以在 aggregation expression 中使用变量 REMOVE 来有条件地抑制/禁止一个字段。有关示例,请参阅 Conditionally Exclude Fields(有条件地排除字段)。
Add New Fields or Reset Existing Fields 添加新字段或重置现有字段
NOTE MongoDB还提供了 $addFields 来向文档添加新字段。
要添加一个新的字段或重置一个现有字段的值,指定字段名并将其值设置为某个 expression 。关于 expressions 的更多信息,参阅 Expressions。
Literal Values 字面值
要将一个字段的值直接设置为数字或布尔值,而不是将字段设置为可解析为字段的 expression,请使用 $literal operator。否则,$project 会将数字或布尔字段视为包括或排除该字段的标志。
Field Rename 重命名字段
通过指定一个新字段并将其值设置为现有字段的 field path,你可以有效地重命名一个字段。
New Array Fields 新的数组字段
$project stage 支持使用方括号 []
来直接创建新的数组字段。如果你指定的数组字段在文档中不存在,该 operation 会将 null
替换为该字段的值。有关示例,请参阅 Project New Array Fields(project 新的数组字段)。
你不能在 $project stage 使用数组索引。参阅 Array Indexes are Unsupported(数组索引不被支持)。
Embedded Document Fields 嵌入式文档字段
当 projecting 或 adding/resetting 一个嵌入式文档中的字段时,你可以使用点符号,如:
"contact.address.country": <1 or 0 or expression>
或者你可以嵌套字段:
contact: { address: { country: <1 or 0 or expression> } }
当嵌套字段时,你不能在嵌入的文档中使用点符号来指定字段,例如,contact: { "address.country": <1 or 0 or expression> }
是无效(invalid)的。
Path Collision Error in Embedded Fields 嵌入字段中的路径冲突错误
你不能在同一个 projection 中同时指定一个嵌入文档和该嵌入文档中的一个字段。
下面的 $project stage 失败了,因为它试图同时 project 嵌入式 contact
文档和 contact.address.country
字段,所以出现了 Path collision error(路径碰撞错误)
。
{ $project: { contact: 1, "contact.address.country": 1 } }
无论指定父文档和嵌入字段的顺序如何,该错误都会发生。下面的 $project 失败了,出现同样的错误:
{ $project: { "contact.address.country": 1, contact: 1 } }
Restrictions 限制
如果 $project 规范是一个空文档,将返回一个错误。
你不能在 $project stage 使用数组索引。参阅 Array Indexes are Unsupported(数组索引不被支持)。
Example 例子
Include Specific Fields in Output Documents 在输出文档中包含特定字段
考虑一个包含以下文档的 books
collection:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}
以下 $project stage 在其输出文档中仅包含 _id
、title
和 author
字段:
db.books.aggregate( [
{ $project: { title: 1, author: 1 } }
] )
该 operation 的结果如以下文档:
{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
Suppress _id
Field in the Output Documents 在输出文档中抑制/禁止 _id
字段
默认情况下,_id
字段总是被包括在内。要从 $project stage 的输出文档中排除 _id
字段,请在 projection 文档中指定排除 _id
字段,将其设置为 0
。
考虑一个包含以下文档的 books
collection:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}
以下 $project stage 不包括 _id
字段,但在其输出文档中包含 title
和 author
字段:
db.books.aggregate( [
{ $project: { _id: 0, title: 1, author: 1 } }
] )
该 operation 结果如以下文档:
{ "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }
Exclude Fields from Output Documents 从输出文档中排除字段
考虑一个包含以下文档的 books
collection:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5,
lastModified: "2016-07-28"
}
下面的 $project stage 从输出中排除了 lastModified
字段:
db.books.aggregate( [
{ $project: { "lastModified": 0 } }
] )
也可参阅 $unset stage,以排除字段。
Exclude Fields from Embedded Documents 从嵌入式文档中排除字段
考虑一个包含以下文档的 books
collection:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5,
lastModified: "2016-07-28"
}
下面的 $project stage 从输出中排除了 author.first
和 lastModified
字段:
db.books.aggregate( [
{ $project: { "author.first": 0, "lastModified": 0 } }
] )
或者,您可以将排除规范嵌套在文档中:
db.books.aggregate( [
{
$project: {
"author": { "first": 0 },
"lastModified": 0
}
}
] )
这两种规范都会产生相同的输出:
{
"_id" : 1,
"title" : "abc123",
"isbn" : "0001122223334",
"author" : {
"last" : "zzz"
},
"copies" : 5,
}
也可参阅 $unset stage,以排除字段。
Conditionally Exclude Fields 有条件地排除字段
你可以在 aggregation expressions 中使用变量 REMOVE 来有条件地抑制/禁止一个字段。
考虑一个包含以下文档的 books
collection:
{
"_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 stage 使用 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"
}
}
}
}
] )
该 aggregation operation 的结果输出如下:
{ "_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 从嵌入式文档中包含指定指端
考虑一个包含以下文档的 bookmarks
collection:
{ _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
字段,你可以使用点符号:
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" } ] }
Include Computed Fields 包含计算字段
考虑一个包含以下文档的 books
colleciton:
{
"_id" : 1,
title: "abc123",
isbn: "0001122223334",
author: { last: "zzz", first: "aaa" },
copies: 5
}
下面的 $project stage 添加了新的字段 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"
}
}
] )
该 operation 结果文档如下:
{
"_id" : 1,
"title" : "abc123",
"isbn" : {
"prefix" : "000",
"group" : "11",
"publisher" : "2222",
"title" : "333",
"checkDigit" : "4"
},
"lastName" : "zzz",
"copiesSold" : 5
}
Project New Array Fields Project 新的数组字段
例如,如果一个 collection 包含以下文档:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "x" : 1, "y" : 1 }
以下 operation 将字段 x
和 y
project 到一个新字段 myArray
中的元素:
db.collection.aggregate( [
{
$project: {
myArray: [ "$x", "$y" ]
}
}
] )
该 operation 返回以下文档:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1 ] }
如果数组规范包含在文档中不存在的字段,则 operation 将 null
作为该字段的值。
例如,给定上述相同的文档,下面的操作将字段 x
、y
和一个不存在的字段 $someField
project 为一个新字段 myArray
中的元素:
db.collection.aggregate( [
{
$project: {
myArray: [ "$x", "$y", "$someField" ]
}
}
] )
该 operation 返回以下文档:
{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1, null ] }
Array Indexes are Unspported
你不能在 $project stage 使用一个数组索引。本节展示了一个例子:
创建以下 pizzas
collection:
db.pizzas.insert( [
{ _id: 0, name: [ 'Pepperoni' ] },
] )
以下示例返回 pizza:
db.pizzas.aggregate( [
{ $project: { x: '$name', _id: 0 } },
] )
pizza 在示例输出中返回:
[ { x: [ 'Pepperoni' ] } ]
下面的例子使用一个数组索引($name.0
)来尝试返回 pizza:
db.pizzas.aggregate( [
{ $project: { x: '$name.0', _id: 0 } },
] )
示例输出中未返回 pizza:
[ { x: [] } ]
TIP 参阅:
- Aggregation with the Zip Code Data Set 用邮编数据集进行 aggregation
- Aggregation with User Preference Data 用用户偏好数据进行 aggregation
参考
https://docs.mongodb.com/manual/reference/operator/aggregation/project