-
Type: New Feature
-
Resolution: Done
-
Priority: Major - P3
-
Affects Version/s: None
-
Component/s: Builders
-
None
Syntax
{$replaceRoot: {newRoot: <expression that evaluates to a document>}}
Examples
// ===== Example #1 - Promoting a subfield to the top level ===== >db.example.insert({_id: 0, a1: {b: 1}, a2: 2}) >db.example.aggregate([{$replaceRoot: {newRoot: “$a1”}}]); {b: 1} // ===== Example #2 - Promoting a nested field to the top level ===== >db.example.insert({_id: 0, a1: {b: {c1: 4, c2: 5}}, a2: 2}) >db.example.aggregate([{$replaceRoot: {newRoot: “$a1.b”}}]) {_id: 0, c1: 4, c2: 5} // ===== Example #3 - Promoting a field that contains an _id ===== >db.example.insert({_id: 0, a1: {b: 1, _id: 7}, a2: 2}) >db.example.aggregate([{$replaceRoot: {newRoot: “$a1”}}]); {b: 1, _id: 7} // ===== Errors #1 - Invalid path syntax ===== >db.example.aggregate([{$replaceRoot: “$a” }]) Error: expected an object as specification for $replaceRoot stage // ===== Error #2 - When the field doesn’t exist ===== >db.example.insert({_id: 0, a1: {b: 1}, a2: 2}) >db.example.aggregate([{$replaceRoot: {newRoot: “$c”}}]) Error: newRoot must resolve to an object // ===== Error #3 - When the field is not an object ===== >db.example.insert({_id: 0, a1: {b: 1}, a2: 2 }) >db.example.aggregate([{$replaceRoot: {newRoot: “$a2”}}]) Error: newRoot must resolve to an object
More Details
- We do not do anything special with the _id field.
- The original _id (if it exists) will be lost. The user can include it by prepending a {$addFields: {“a._id”: “$_id”}} stage. Any _id field in the new root will not be moved to the front for display.
Original Description
In some cases, the documents of interest in the aggregation pipeline are nested inside an outer document. For example, if I had a schema like this:
{ _id: "user_id", first: "first name", last: "last name", addresses: [ {city: "New York", state: "NY", zip: "10036", address: "229 W 43rd"}, {city: "Palo Alto", state: "CA", zip: "94301", address: "100 Forest Ave"} ... ] }
Then I might have an aggregation pipeline which deals exclusively with the contents of 'addresses'. It's currently possible to do this, first by unwinding 'addresses', but this approach becomes annoying since all of the field names need to be prefixed with 'addresses.'. It would be useful to have some stage to promote the document inside 'addresses' to the top field. For example, something like this:
db.users.aggregate([ {$unwind: "$addresses"}, {$transform: {root: "$addresses"}} ]) {city: "New York", state: "NY", zip: "10036", address: "229 W 43rd"} {city: "Palo Alto", state: "CA", zip: "94301", address: "100 Forest Ave"}
Such a stage could also support other transformations, like those possible in $project, or some that are not possible, such as adding a field to a document (SERVER-5781).
- depends on
-
SERVER-23313 Add a $replaceRoot stage which allows promoting a sub-document to the top level
- Closed
- is depended on by
-
DRIVERS-297 Aggregation Framework Support for 3.4
- Closed