Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs 菜单
Docs 主页
/ /

$addFields(聚合阶段)

$addFields

为文档添加新字段。$addFields 输出文档包含输入文档中的所有现有字段和新添加的字段。

$addFields 阶段等效于 $project 阶段,后者明确指定输入文档中的所有现有字段并添加新字段。

注意

您还可以使用 $set 阶段,它是 $addFields 的别名。

可以使用 $addFields 查找托管在以下环境中的部署:

  • MongoDB Atlas:用于云中 MongoDB 部署的完全托管服务

该阶段采用以下语法:

{ $addFields: { <newField>: <expression>, ... } }

指定要添加的每个字段的名称,并将其值设立为聚合表达式或空对象。有关表达式的更多信息,请参阅表达式。

重要

如果新字段名称与现有字段名称(包括 _id)相同,$addFields 将用指定表达式的值覆盖该字段的现有值。

  • $addFields 将新字段附加到现有文档。可以在聚合操作中包含一个或多个 $addFields 阶段。

  • $addFields 接受对象的嵌入,您可以将值设置为聚合表达式或空对象。例如,接受以下嵌套对象:

    {$addFields: { a: { b: { } } } }

    要将一个或多个字段添加到嵌入式文档(包括数组中的文档),请使用点表示法。请参阅示例

  • 要使用 $addFields 向现有数组字段添加元素,请与 $concatArrays 一起使用。请参阅示例

本页上的示例使用 sample_mflix示例数据集 中的数据。有关如何将此数据集加载到自管理MongoDB 部署中的详细信息,请参阅加载示例数据集。如果对示例数据库进行了任何修改,则可能需要删除并重新创建数据库才能运行本页上的示例。

以下操作使用两个 $addFields 阶段,首先将运行时间转换为小时数,然后按每小时 0.50 美元计算许可费用:

db.movies.aggregate( [
{ $match: { runtime: { $gt: 1000 } } },
{
$addFields: {
runtimeHours: {
$floor: { $divide: [ "$runtime", 60 ] }
},
ratingOutOf100: { $multiply: [ "$imdb.rating", 10 ] }
}
},
{
$addFields: {
licenseFeeUSD: {
$multiply: [ "$runtimeHours", 0.50 ]
}
}
}
] )
[
{ _id: ..., title: 'Baseball', runtime: 1140, runtimeHours: 19, licenseFeeUSD: 9.5 },
{ _id: ..., title: 'Centennial', runtime: 1256, runtimeHours: 20, licenseFeeUSD: 10 }
]
...

使用点符号为嵌入式文档添加新字段。

以下聚合操作将 certified字段添加到每部电影的嵌入式 imdb文档中:

db.movies.aggregate( [
{ $match: { runtime: { $gt: 1000 } } },
{ $addFields: { "imdb.certified": true } }
] )
[
{ _id: ..., title: 'Baseball', imdb: { certified: true, '...': '...' } },
{ _id: ..., title: 'Centennial', imdb: { certified: true, '...': '...' } }
]
...

$addFields 操作中指定现有字段名称会导致原始字段被替换。

以下 $addFields 操作会覆盖 runtime字段以添加 15 分钟:

db.movies.aggregate( [
{ $match: { runtime: { $gt: 1000 } } },
{
$addFields: { runtime: { $add: [ "$runtime", 15 ] } }
}
] )
[
{ _id: ..., title: 'Baseball', runtime: 1155 },
{ _id: ..., title: 'Centennial', runtime: 1271 }
]
...

您还可以将一个字段替换为另一个字段。以下操作将 _id 设置为电影的标题,并将 title字段替换为电影的主节点 (primary node in the replica set)类型:

db.movies.aggregate( [
{ $match: { runtime: { $gt: 1000 } } },
{
$addFields: {
_id: "$title",
title: { $arrayElemAt: [ "$genres", 0 ] }
}
}
] )
[
{ _id: 'Baseball', title: 'Documentary' },
{ _id: 'Centennial', title: 'Action' }
]
...

可以使用 $addFields$concatArrays 表达式向现有数组字段添加元素。以下操作将 Epic 追加到标题为 Centennial 的电影的 genres数组中:

db.movies.aggregate( [
{ $match: { title: "Centennial" } },
{ $addFields: {
genres: {
$concatArrays: [ "$genres", [ "Epic" ] ]
}
} }
] )
[
{ _id: ..., title: 'Centennial', genres: [ 'Action', 'Adventure', 'Drama', 'Epic' ] }
]
...

您可以使用 $addFields$$REMOVE 变量来删除文档字段。

以下操作使用 $addFields删除附带 $$REMOVE 变量的 plot字段:

db.movies.aggregate( [
{ $match: { runtime: { $gt: 1000 } } },
{
$addFields: { plot: "$$REMOVE" }
}
] )
[
{ _id: ..., title: 'Baseball', runtime: 1140 },
{ _id: ..., title: 'Centennial', runtime: 1256 }
]
...

您也可以使用 $$REMOVE 有条件地删除字段。例如,以下聚合从 ratednull 的文档中删除 rated 字段:

db.movies.aggregate( [
{ $match: { runtime: { $gt: 1000 } } },
{
$addFields:
{
rated: {
$ifNull: [ "$rated", "$$REMOVE" ]
}
}
}
] )
[
{ _id: ..., title: 'Baseball', rated: 'TV-PG' },
{ _id: ..., title: 'Centennial' }
]
...

本页上的 Node.js 示例使用 Atlas 示例数据集中的 sample_mflix数据库。要学习如何创建免费的MongoDB Atlas 集群并加载示例数据集,请参阅MongoDB Node.js驱动程序文档中的入门

要使用MongoDB Node.js驱动程序将 $addFields 阶段添加到聚合管道,请在管道对象中使用 $addFields操作符。

以下示例创建了一个管道阶段,该阶段向每个电影文档添加一个 totalReviews字段,其中包含电影的评论总数。然后,该示例运行聚合管道:

const pipeline = [
{
$addFields: {
totalReviews: {
$add: ["$imdb.votes", "$tomatoes.viewer.numReviews"]
}
}
}
];
const cursor = collection.aggregate(pipeline);
return cursor;

提示

与 $project 的比较

您可以使用 $addFields$project 阶段删除文档字段。最佳方法取决于您的管道以及您希望保留多少原始文档。

有关在 $project 阶段使用 $$REMOVE 的示例,请参阅有条件地排除字段

要学习;了解有关相关管道阶段的更多信息,请参阅 $project$set 指南。

后退

聚合阶段

在此页面上