Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-2287

Add builder for $replaceRoot aggregation stage

    XMLWordPrintable

    Details

    • Type: New Feature
    • Status: Closed
    • Priority: Major - P3
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 3.4.0
    • Component/s: Builders
    • Labels:
      None
    • Sprint:
      JVM Sprint 35

      Description

      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).

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: