$replaceRoot (aggregation)
Definition
$replaceRootReplaces the input document with the specified document. The operation replaces all existing fields in the input document, including the
_idfield. You can promote an existing embedded document to the top level, or create a new document for promotion (see example).Note
You can also use the
$replaceWithstage. The$replaceWithstage peforms the same action as the$replaceRootstage, but the stages have different forms.The
$replaceRootstage has the following form:{ $replaceRoot: { newRoot: <replacementDocument> } } The replacement document can be any valid expression that resolves to a document. The stage errors and fails if
<replacementDocument>is not a document. For more information on expressions, see Expression Operators.
Behavior
If the <replacementDocument> is not a document,
$replaceRoot errors and fails.
If the <replacementDocument> resolves to a missing document (i.e.
the document does not exist), $replaceRoot errors and
fails. For example, create a collection with the following
documents:
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 $replaceRoot operation fails because one
of the documents does not have the name field:
db.collection.aggregate([    { $replaceRoot: { newRoot: "$name" } } ]) 
To avoid the error, you can use $mergeObjects to merge
the name document into some default document; for example:
db.collection.aggregate([    { $replaceRoot: { newRoot: { $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 $replaceRoot
stage:
db.collection.aggregate([    { $match: { name : { $exists: true, $not: { $type: "array" }, $type: "object" } } },    { $replaceRoot: { newRoot: "$name" } } ]) 
Or, you can use $ifNull expression to specify some other
document to be root; for example:
db.collection.aggregate([    { $replaceRoot: { newRoot: { $ifNull: [ "$name", { _id: "$_id", missingName: true} ] } } } ]) 
Examples
$replaceRoot with an Embedded Document Field
A collection named people contains the following documents:
{ "_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 $replaceRoot stage to
replace each input document with the result of a
$mergeObjects operation. The $mergeObjects
expression merges the specified default document with the pets
document.
db.people.aggregate( [    { $replaceRoot: { newRoot: { $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 } 
$replaceRoot with a Document Nested in an Array
A collection named students contains the following documents:
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:
db.students.aggregate( [    { $unwind: "$grades" },    { $match: { "grades.grade" : { $gte: 90 } } },    { $replaceRoot: { newRoot: "$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 } 
$replaceRoot with a newly created document
You can also create new documents as part of the
$replaceRoot stage and use them to replace all the other fields.
A collection named contacts contains the following documents:
{ "_id" : 1, "first_name" : "Gary", "last_name" : "Sheffield", "city" : "New York" } { "_id" : 2, "first_name" : "Nancy", "last_name" : "Walker", "city" : "Anaheim" } { "_id" : 3, "first_name" : "Peter", "last_name" : "Sumner", "city" : "Toledo" } 
The following operation creates a new document out of the
first_name and last_name fields.
db.contacts.aggregate( [    {       $replaceRoot: {          newRoot: {             full_name: {                $concat : [ "$first_name", " ", "$last_name" ]             }          }       }    } ] ) 
The operation returns the following results:
{ "full_name" : "Gary Sheffield" } { "full_name" : "Nancy Walker" } { "full_name" : "Peter Sumner" } 
$replaceRoot with a New Document Created from $$ROOT and a Default Document
Create a collection named contacts with the following documents:
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", home: "987-654-3210", email: "beo@example.net" } ] ) 
The following operation uses $replaceRoot with
$mergeObjects to output current documents with default
values for missing fields:
db.contacts.aggregate( [    { $replaceRoot:       { newRoot:          { $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' } 
The C# examples on this page use the sample_mflix database
from the Atlas sample datasets. 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.
The following Movie class models the documents in the sample_mflix.movies
collection:
public class Movie {     public string 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; } } 
The following class models ImdbData documents:
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 $replaceRoot stage to an aggregation
pipeline, call the ReplaceRoot() method on a PipelineDefinition object.
The following example creates a pipeline stage that replaces each input Movie document with the ImdbData document stored
in its Imdb property:
var pipeline = new EmptyPipelineDefinition<Movie>()     .ReplaceRoot(m => m.ImdbData);