$project
聚合阶段可将输入文档根据请求的字段输出到管道的下个阶段,输出的字段可以是输入文档中的字段,也可以是新的计算字段。
语法
{
$project: {
<specification(s)> } }
$project
聚合接受一个文档参数,可以指定包含的字段,抑制_id
字段,添加新的字段以及重置已有字段的值等。亦或者,也可以指定排除的字段。
$project
的参数字段可以是下面的形式:
参数字段形式 | 描述 |
---|---|
<字段>:<1或true> |
指定包含的字段,非0整数也被视为true |
_id:<0或false> |
指定抑制_id 字段,也就是_id 字段不会被传递到下个阶段。也可以使用REMOVE 变量和条件排除字段 |
<字段>:<表达式> |
添加一个新字段或者重置已有字段的值。如果表达式的值为$$REMOVE ,则字段被排除 |
<字段>:<0或false> |
排除一个指定的字段。可以使用REMOVE 变量和条件排除字段,如果排除_id 以外的字段,则不能同时使用其他形式,但是REMOVE 变量条件排除字段除外 |
使用
包含现有字段
_id
字段默认输出,如果要包含其他字段,必须明确的指定。- 如果指定要包含的字段在输入文档中不存在,
$project
将忽略该字段,输出文档中也不会包含该字段。
抑制_id
字段
缺省情况下输出文档包含_id
字段,如果不想让_id
字段出现在输出文档中必须显示的指定抑制_id
字段。
排除字段
如果指定了排除字段,没有被指定的字段默认输出到下个阶段。
{
$project: {
"<field1>": 0, "<field2>": 0, ... } } // 将返回所有没有被指定的字段
如果指定了排除_id
字段以外的其他字段,则不能再使用其他形式来指定字段,也就是说这种情况下不能再指定包含其他字段,也不能指定新的字段或重置已有字段。但可以使用REMOVE
变量条件排除字段。
条件排除字段
可以使用REMOVE
变量根据表达式条件抑制一个字段。
添加字段或重置已有字段
**注意:**也可以使用$addFields
来为文档添加字段。
要添加一个字段或重置已有字段的值,可以指定字段名并使用表达式指定值
字面量值
要将字段值直接设置为数字或布尔字面量,而不是将字段设置为解析为字面量的表达式,可使用$literal
操作符。否则,$project
将把数字或布尔字面量视为包含或排除字段的标志。
修改字段名
通过指定一个新字段并将其值设置为现有字段的字段路径,可以重命名一个字段。
新增数组字段
$project
阶段支持使用方括号[]
直接创建新的数组字段,如果指定的数组字段在文档中不存在,则操作会将空值替换为该字段的值。
内嵌文档字段
当重塑、添加或重置内嵌文档的字段时,可以使用点号或嵌套字段:
点号形式:
"contact.address.country": <1 or 0 or 表达式>
嵌套字段形式:
contact: {
address: {
country: <1 or 0 or 表达式> } }
当使用嵌套字段时,不能在嵌套文档内部使用点号指定字段,如下面的就是错误的方式:
contact: {
"address.country": <1 or 0 or 表达式> }
内嵌文档字段的路径冲突错误
不能在同一投影中同时指定嵌入文档和嵌入文档中的字段。下面的$project
阶段有路径冲突错误,因为试图同时重塑内嵌文档contact
和contact.address.country
字段:
{
$project: {
contact: 1, "contact.address.country": 1 } }
这种错误与父文档和内嵌字段的顺序无关,下面的$project
是同样的错误:
{
$project: {
"contact.address.country": 1, contact: 1 } }
$project
阶段的位置
当使用$project
截断式,通常情况下它应该放在管道的最后阶段,用它来指定返回给客户端的字段。
没有必要为了减少传递到后续管道的字段数量而把$project
阶段放在管道的开始或中间,这也不太可能提高性能,数据库会自动执行这种优化。
限制
- 给
$project
制定一个空文档会返回错误。 - 在
$project
阶段中不能使用数组下标。
举例
输出文档中包含指定字段
有一个book
集合包含下面的文档:
{
"_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
字段,如果要在输出文档中排除_id
字段,可以在参数中给_id
指定0
。
books
集合中有下面的文档:
{
"_id" : 1,