对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

$addFields(聚合阶段)

$addFields

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

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

注意

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

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

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

该阶段采用以下语法:

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

指定要添加的每个字段的名称,并将其值设置为聚合表达式或空对象。

重要

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

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

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

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

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

  • 要使用 $addFields 向现有数组字段添加元素,请使用 $concatArrays。See 示例.

本页上的示例使用来自 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 有条件地删除字段。例如,以下聚合从 rated 为 null 的文档中删除 rated 字段:

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

提示

与 $project 的比较

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

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

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