- Definition 定义
- Considerations 注意事项
- Example 例子
- Include Specific Fields in Output Documents 在输出文档中包含特定字段
- Suppress
_idField 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
默认情况下,_idField 抑制/禁止_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
