Definition定义
$replaceWithReplaces the input document with the specified document. The operation replaces all existing fields in the input document, including the用指定的文档替换输入文档。该操作将替换输入文档中的所有现有字段,包括_idfield._id字段。With使用$replaceWith, you can promote an embedded document to the top-level. You can also specify a new document as the replacement.$replaceWith,您可以将嵌入式文档提升到顶级。您还可以指定一个新文档作为替换。The$replaceWithstage performs the same action as the$replaceRootstage, but the stages have different forms.$replaceWith阶段执行与$replaceRoot阶段相同的操作,但阶段的形式不同。The$replaceWithstage has the following form:$replaceWith阶段具有以下形式:{ $replaceWith: <replacementDocument> }The replacement document can be any valid expression that resolves to a document. For more information on expressions, see Expressions.替换文档可以是解析为文档的任何有效表达式。有关表达式的详细信息,请参阅表达式。
Behavior行为
If the 如果<replacementDocument> is not a document, $replaceWith errors and fails.<replacementDocument>不是文档,$replaceWith将出错并失败。
If the 如果<replacementDocument> resolves to a missing document (i.e. the document does not exist), $replaceWith errors and fails. For example, create a collection with the following documents:<replacementDocument>解析为缺少文档(即文档不存在),$replaceWith将出错并失败。例如,使用以下文档创建一个集合:
db.collection.insertMany([
{ "_id": 1, "name" : { "first" : "John", "last" : "Backus" } },
{ "_id": 2, "name" : { "first" : "John", "last" : "McCarthy" } },
{ "_id": 3, "name": { "first" : "Grace", "last" : "Hopper" } },
{ "_id": 4, "firstname": "Ole-Johan", "lastname" : "Dahl" },
])
Then the following 然后,以下$replaceWith operation fails because one of the document does not have the name field:$replaceWith操作失败,因为其中一个文档没有name字段:
db.collection.aggregate([
{ $replaceWith: "$name" }
])
To avoid the error, you can use 为了避免错误,您可以使用$mergeObjects to merge the name document with some default document; for example:$mergeObjects将名称文档与一些默认文档合并;例如:
db.collection.aggregate([
{ $replaceWith: { $mergeObjects: [ { _id: "$_id", first: "", last: "" }, "$name" ] } }
])
Alternatively, you can skip the documents that are missing the 或者,您可以跳过缺少name field by including a $match stage to check for existence of the document field before passing documents to the $replaceWith stage:name字段的文档,方法是在将文档传递给$replaceWith阶段之前,包含一个$match阶段来检查文档字段的存在:
db.collection.aggregate([
{ $match: { name : { $exists: true, $not: { $type: "array" }, $type: "object" } } },
{ $replaceWith: "$name" }
])
Or, you can use 或者,您可以使用$ifNull expression to specify some other document to be root; for example:$ifNull表达式将其他文档指定为根;例如:
db.collection.aggregate([
{ $replaceWith: { $ifNull: [ "$name", { _id: "$_id", missingName: true} ] } }
])Examples示例
MongoDB Shell
$replaceWith an Embedded Document Field嵌入式文档字段
Create a collection named 使用以下文档创建一个名为people with the following documents:people的集合:
db.people.insertMany([
{ "_id" : 1, "name" : "Arlene", "age" : 34, "pets" : { "dogs" : 2, "cats" : 1 } },
{ "_id" : 2, "name" : "Sam", "age" : 41, "pets" : { "cats" : 1, "fish" : 3 } },
{ "_id" : 3, "name" : "Maria", "age" : 25 }
])
The following operation uses the 以下操作使用$replaceWith stage to replace each input document with the result of a $mergeObjects operation. $replaceWith阶段将每个输入文档替换为$mergeObjects操作的结果。The $mergeObjects expression merges the specified default document with the pets document.$mergeObjects表达式将指定的默认文档与pets文档合并。
db.people.aggregate( [
{ $replaceWith: { $mergeObjects: [ { dogs: 0, cats: 0, birds: 0, fish: 0 }, "$pets" ] } }
] )
The operation returns the following results:该操作返回以下结果:
{ "dogs" : 2, "cats" : 1, "birds" : 0, "fish" : 0 }
{ "dogs" : 0, "cats" : 1, "birds" : 0, "fish" : 3 }
{ "dogs" : 0, "cats" : 0, "birds" : 0, "fish" : 0 }$replaceWith a Document Nested in an Array嵌套在数组中的文档
A collection named 名为students contains the following documents:students的集合包含以下文档:
db.students.insertMany([
{
"_id" : 1,
"grades" : [
{ "test": 1, "grade" : 80, "mean" : 75, "std" : 6 },
{ "test": 2, "grade" : 85, "mean" : 90, "std" : 4 },
{ "test": 3, "grade" : 95, "mean" : 85, "std" : 6 }
]
},
{
"_id" : 2,
"grades" : [
{ "test": 1, "grade" : 90, "mean" : 75, "std" : 6 },
{ "test": 2, "grade" : 87, "mean" : 90, "std" : 3 },
{ "test": 3, "grade" : 91, "mean" : 85, "std" : 4 }
]
}
])
The following operation promotes the embedded document(s) with the 以下操作将grade field greater than or equal to 90 to the top level:grade字段大于或等于90的嵌入文档提升到顶级:
db.students.aggregate( [
{ $unwind: "$grades" },
{ $match: { "grades.grade" : { $gte: 90 } } },
{ $replaceWith: "$grades" }
] )
The operation returns the following results:该操作返回以下结果:
{ "test" : 3, "grade" : 95, "mean" : 85, "std" : 6 }
{ "test" : 1, "grade" : 90, "mean" : 75, "std" : 6 }
{ "test" : 3, "grade" : 91, "mean" : 85, "std" : 4 }$replaceWith a Newly Created Document新创建的文档
Example 1示例1
An example collection 示例集合sales is populated with the following documents:sales包含以下文档:
db.sales.insertMany([
{ "_id" : 1, "item" : "butter", "price" : 10, "quantity": 2, date: ISODate("2019-03-01T08:00:00Z"), status: "C" },
{ "_id" : 2, "item" : "cream", "price" : 20, "quantity": 1, date: ISODate("2019-03-01T09:00:00Z"), status: "A" },
{ "_id" : 3, "item" : "jam", "price" : 5, "quantity": 10, date: ISODate("2019-03-15T09:00:00Z"), status: "C" },
{ "_id" : 4, "item" : "muffins", "price" : 5, "quantity": 10, date: ISODate("2019-03-15T09:00:00Z"), status: "C" }
])
Assume that for reporting purposes, you want to calculate for each completed sale, the total amount as of the current report run time. 假设出于报告目的,您想计算截至当前报告运行时的每笔已完成销售的总金额。The following operation finds all the sales with status 以下操作将查找状态为C and creates new documents using the $replaceWith stage. C的所有销售,并使用$replaceWith阶段创建新文档。The $replaceWith calculates the total amount as well as uses the variable NOW to get the current time.$replaceWith计算总金额,并使用变量NOW获取当前时间。
db.sales.aggregate([
{ $match: { status: "C" } },
{ $replaceWith: { _id: "$_id", item: "$item", amount: { $multiply: [ "$price", "$quantity"]}, status: "Complete", asofDate: "$$NOW" } }
])
The operation returns the following documents:该操作返回以下文档:
{ "_id" : 1, "item" : "butter", "amount" : 20, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }
{ "_id" : 3, "item" : "jam", "amount" : 50, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }
{ "_id" : 4, "item" : "muffins", "amount" : 50, "status" : "Complete", "asofDate" : ISODate("2019-06-03T22:47:54.812Z") }Example 2示例2
An example collection 一个示例集合报告销售中按季度和地区填充了报告的销售信息:reportedsales is populated with the reported sales information by quarter and regions:
db.reportedsales.insertMany( [
{ _id: 1, quarter: "2019Q1", region: "A", qty: 400 },
{ _id: 2, quarter: "2019Q1", region: "B", qty: 550 },
{ _id: 3, quarter: "2019Q1", region: "C", qty: 1000 },
{ _id: 4, quarter: "2019Q2", region: "A", qty: 660 },
{ _id: 5, quarter: "2019Q2", region: "B", qty: 500 },
{ _id: 6, quarter: "2019Q2", region: "C", qty: 1200 }
] )
Assume that for reporting purposes, you want to view the reported sales data by quarter; e.g.假设出于报告目的,您想按季度查看报告的销售数据;如。
{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }
To view the data grouped by quarter, you can use the following aggregation pipeline:要查看按季度分组的数据,可以使用以下聚合管道:
db.reportedsales.aggregate( [
{ $addFields: { obj: { k: "$region", v: "$qty" } } },
{ $group: { _id: "$quarter", items: { $push: "$obj" } } },
{ $project: { items2: { $concatArrays: [ [ { "k": "_id", "v": "$_id" } ], "$items" ] } } },
{ $replaceWith: { $arrayToObject: "$items2" } }
] )
First stage:第一阶段:The$addFieldsstage adds a newobjdocument field that defines the keykas the region value and the valuevas the quantity for that region. For example:$addFields阶段添加了一个新的obj文档字段,该字段将键k定义为区域值,将值v定义为该区域的数量。例如:{ "_id" : 1, "quarter" : "2019Q1", "region" : "A", "qty" : 400, "obj" : { "k" : "A", "v" : 400 } }Second stage:第二阶段:The$groupstage groups by the quarter and uses$pushto accumulate theobjfields into a newitemsarray field. For example:$group阶段按季度分组,并使用$push将obj字段累积到新的items数组字段中。例如:{ "_id" : "2019Q1", "items" : [ { "k" : "A", "v" : 400 }, { "k" : "B", "v" : 550 }, { "k" : "C", "v" : 1000 } ] }Third stage:第三阶段:The$projectstage uses$concatArraysto create a new arrayitems2that includes the_idinfo and the elements from theitemsarray:$project阶段使用$concatArrays创建一个新的数组items2,其中包括_id信息和items数组中的元素:{ "_id" : "2019Q1", "items2" : [ { "k" : "_id", "v" : "2019Q1" }, { "k" : "A", "v" : 400 }, { "k" : "B", "v" : 550 }, { "k" : "C", "v" : 1000 } ] }Fourth stage:第四阶段:The$replaceWithuses the$arrayToObjectto convert theitems2into a document, using the specified keykand valuevpairs and outputs that document to the next stage. For example:$replaceWith使用$arrayToObject将items2转换为文档,使用指定的键k和值v对,并将该文档输出到下一阶段。例如:{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }
The aggregation returns the following document:聚合返回以下文档:
{ "_id" : "2019Q1", "A" : 400, "B" : 550, "C" : 1000 }
{ "_id" : "2019Q2", "A" : 660, "B" : 500, "C" : 1200 }$replaceWith a New Document Created from $$ROOT and a Default Document$replaceWith从$$ROOT和默认文档创建的新文档
$replaceWith a New Document Created from $$ROOT and a Default DocumentCreate a collection named 使用以下文档创建一个名为contacts with the following documents:contacts的集合:
db.contacts.insertMany( [
{ "_id" : 1, name: "Fred", email: "fred@example.net" },
{ "_id" : 2, name: "Frank N. Stine", cell: "012-345-9999" },
{ "_id" : 3, name: "Gren Dell", cell: "987-654-3210", email: "beo@example.net" }
] )
The following operation uses 以下操作使用$replaceWith with $mergeObjects to output current documents with default values for missing fields:$replaceWith和$mergeObjects来输出当前文档,并为缺失的字段设置默认值:
db.contacts.aggregate( [
{ $replaceWith:
{ $mergeObjects:
[
{ _id: "", name: "", email: "", cell: "", home: "" },
"$$ROOT"
]
}
}
] )
The aggregation returns the following documents:聚合返回以下文档:
{
_id: 1,
name: 'Fred',
email: 'fred@example.net',
cell: '',
home: ''
},
{
_id: 2,
name: 'Frank N. Stine',
email: '',
cell: '012-345-9999',
home: ''
},
{
_id: 3,
name: 'Gren Dell',
email: 'beo@example.net',
cell: '',
home: '987-654-3210'
}C#
The C# examples on this page use the 本页上的C#示例使用Atlas示例数据集中的sample_mflix database from the Atlas sample datasets. sample_mflix数据库。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB .NET/C# Driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB NET/C#驱动程序文档中的入门。
The following 以下Movie class models the documents in the sample_mflix.movies collection:Movie类对sample_mflix.movies集合中的文档进行建模:
public class Movie
{
public ObjectId Id { get; set; }
public int Runtime { get; set; }
public string Title { get; set; }
public string Rated { get; set; }
public List<string> Genres { get; set; }
public string Plot { get; set; }
public ImdbData Imdb { get; set; }
public int Year { get; set; }
public int Index { get; set; }
public string[] Comments { get; set; }
[]
public DateTime LastUpdated { get; set; }
}
Note
ConventionPack for Pascal CasePascal大小写的约定包
The C# classes on this page use Pascal case for their property names, but the field names in the MongoDB collection use camel case. To account for this difference, you can use the following code to register a 此页面上的C#类使用Pascal大小写作为其属性名,但MongoDB集合中的字段名使用驼峰大小写。为了解释这种差异,您可以在应用程序启动时使用以下代码注册ConventionPack when your application starts:ConventionPack:
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() };
ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);The following class models 以下类对ImdbData documents:ImdbData文档进行建模:
public class ImdbData
{
public string Id { get; set; }
public int Votes { get; set; }
public float Rating { get; set; }
}
To use the MongoDB .NET/C# driver to add a 要使用MongoDB NET/C#驱动程序向聚合管道添加$replaceWith stage to an aggregation pipeline, call the ReplaceWith() method on a PipelineDefinition object.$replaceWith阶段,请在PipelineDefinition对象上调用ReplaceWith()方法。
The following example creates a pipeline stage that replaces each input 以下示例创建了一个管道阶段,该阶段将每个输入的Movie document with the ImdbData document stored in its Imdb property:Movie文档替换为存储在其Imdb属性中的ImdbData文档:
var pipeline = new EmptyPipelineDefinition<Movie>()
.ReplaceWith(m => m.ImdbData);Node.js
The Node.js examples on this page use the 本页上的Node.js示例使用Atlas示例数据集中的sample_mflix database from the Atlas sample datasets. sample_mflix数据库。To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see Get Started in the MongoDB Node.js driver documentation.要了解如何创建免费的MongoDB Atlas集群并加载示例数据集,请参阅MongoDB Node.js驱动程序文档中的入门。
To use the MongoDB Node.js driver to add a 要使用MongoDB Node.js驱动程序将$replaceWith stage to an aggregation pipeline, use the $replaceWith operator in a pipeline object.$replaceWith阶段添加到聚合管道中,请在管道对象中使用$replaceWith运算符。
The following example creates a pipeline stage that replaces each input 以下示例创建了一个管道阶段,将每个输入的movie document with the document stored in its imdb field. The example then runs the aggregation pipeline:movie文档替换为存储在其imdb字段中的文档。然后,该示例运行聚合管道:
const pipeline = [{ $replaceWith: { replacement: "$imdb" } }];
const cursor = collection.aggregate(pipeline);
return cursor;Learn More了解更多
To learn more about related pipeline stages, see the 要了解有关相关管道阶段的更多信息,请参阅$replaceRoot guide.$replaceRoot指南。