$project(聚合)

在本页面

  • 定义

  • 注意事项

  • 例子

定义

  • $project

    • 将包含请求字段的文档传递到管道中的下一个阶段。指定的字段可以是输入文档或新计算字段中的现有字段。

$project阶段具有以下原型形式:

{ $project: { <specification(s)> } }

$project采用可以指定字段包含,_id字段抑制,新字段添加以及重置现有字段值的文档。或者,您可以指定字段的排除。

$project规范具有以下形式:

形成描述
<field>: <1 or true>指定包含字段。
_id: <0 or false>指定_id字段的抑制。
要有条件地排除字段,请改用去掉变量。有关详细信息,请参阅有条件地排除字段。
<field>: <expression>添加新字段或重置现有字段的 value。
在 version 3.6 中更改:MongoDB 3.6 添加变量去掉。如果表达式求值为$$REMOVE,则在输出中排除该字段。有关详细信息,请参阅有条件地排除字段。
<field>:<0 or false>version 3.4 中的新功能。
指定排除字段。
要有条件地排除字段,请改用去掉变量。有关详细信息,请参阅有条件地排除字段。
如果指定排除_id以外的字段,则不能使用任何其他$project规范表单。此限制不适用于使用去掉变量有条件地排除字段。

注意事项

包括现有字段

  • 默认情况下,_id字段包含在输出文档中。要在输出文档中包含输入文档中的任何其他字段,必须在$project中明确指定包含。

  • 如果指定包含文档中不存在的字段,则$project将忽略该字段包含,并且不会将该字段添加到文档中。

取消_id 字段

默认情况下,_id字段包含在输出文档中。要从输出文档中排除_id字段,必须在$project中明确指定_id字段的抑制。

排除字段

version 3.4 中的新内容。

如果指定排除某个或多个字段,则在输出文档中返回所有其他字段。

如果指定排除_id以外的字段,则不能使用任何其他$project规范表单:i.e。如果排除字段,则不能同时指定字段的包含,重置现有字段的 value 或添加新字段。此限制不适用于使用去掉变量对字段进行条件排除。

有条件地排除字段

version 3.6 中的新内容。

从 MongoDB 3.6 开始,您可以在聚合表达式中使用变量去掉来有条件地抑制字段。对于 example,请参阅有条件地排除字段。

添加新字段或重置现有字段

注意
MongoDB 还提供$addFields以向文档添加新字段。

要添加新字段或重置现有字段的 value,请指定字段 name 并将其 value 设置为某个表达式。有关表达式的更多信息,请参阅表达式。

文字价值观

要将字段 value 直接设置为数字或 boolean 文字,而不是将字段设置为解析为文字的表达式,请使用$literal operator。否则,$project将数字或 boolean 文字视为包含或排除字段的 flag。

现场重命名

通过指定新字段并将其 value 设置为现有字段的字段路径,可以有效地重命名字段。

新的 Array Fields

从 MongoDB 3.2 开始,$project stage 支持使用方括号[]直接创建新的 array 字段。如果 array 规范包含文档中 non-existent 的字段,则该操作将null替换为该字段的 value。对于 example,请参阅Project New Array Fields。

嵌入文档字段

在嵌入文档中投影或 adding/resetting 字段时,可以使用点符号,如

"contact.address.country": <1 or 0 or expression>

或者您可以嵌套字段:

contact: { address: { country: <1 or 0 or expression> } }

嵌套字段时,不能在嵌入文档中使用点表示法来指定字段 e.g. contact: { "address.country": <1 or 0 or expression> }无效。

限制

更改了 version 3.4.

如果$project规范是空文档,则 MongoDB 3.4 及更高版本会产生错误。

例子

在输出文档中包含特定字段

考虑带有以下文档的books集合:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5
}

以下$project阶段仅在其输出文档中包含_idtitleauthor字段:

db.books.aggregate( [ { $project : { title : 1 , author : 1 } } ] )

操作结果如下:

{ "_id" : 1, "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }

禁止输出文档中的_id 字段

默认情况下始终包含_id字段。要从$project阶段的输出文档中排除_id字段,请通过在投影文档中将其设置为0来指定排除_id字段。

考虑带有以下文档的books集合:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5
}

以下$project阶段排除了_id字段,但在其输出文档中包含titleauthor字段:

db.books.aggregate( [ { $project : { _id: 0, title : 1 , author : 1 } } ] )

操作结果如下:

{ "title" : "abc123", "author" : { "last" : "zzz", "first" : "aaa" } }

从输出文档中排除字段

version 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 } } ] )

从嵌入式文档中排除字段

version 3.4 中的新内容。

考虑带有以下文档的books集合:

{
  "_id" : 1,
  title: "abc123",
  isbn: "0001122223334",
  author: { last: "zzz", first: "aaa" },
  copies: 5,
  lastModified: "2016-07-28"
}

以下$project阶段从输出中排除author.firstlastModified字段:

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

有条件地排除字段

version 3.6 中的新内容。

从 MongoDB 3.6 开始,您可以在聚合表达式中使用变量去掉来有条件地抑制字段。

考虑带有以下文档的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等于""时才使用去掉变量排除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字段,可以使用点符号:

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阶段添加新字段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"
         }
      }
   ]
)

操作结果如下:

{
   "_id" : 1,
   "title" : "abc123",
   "isbn" : {
      "prefix" : "000",
      "group" : "11",
      "publisher" : "2222",
      "title" : "333",
      "checkDigit" : "4"
   },
   "lastName" : "zzz",
   "copiesSold" : 5
}

Project New Array Fields

对于 example,如果集合包含以下文档:

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "x" : 1, "y" : 1 }

以下操作将字段xy投影为新字段myArray中的元素:

db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y" ] } } ] )

该操作返回以下文档:

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1 ] }

如果 array 规范包含文档中 non-existent 的字段,则该操作将null替换为该字段的 value。

对于 example,给定与上面相同的文档,以下操作将字段xy和 non-existing 字段$someField投影为新字段myArray中的元素:

db.collection.aggregate( [ { $project: { myArray: [ "$x", "$y", "$someField" ] } } ] )

该操作返回以下文档:

{ "_id" : ObjectId("55ad167f320c6be244eb3b95"), "myArray" : [ 1, 1, null ] }

也可以看看
使用 Zip Code 数据集进行聚合,使用用户首选项数据进行聚合