Search code examples
arraysmongodbmultidimensional-arraymongodb-querymongodb-update

Rename field name in nested array of subdocuments for all documents


I have a collection like this:

[
  {
    "variants": [
      {
        "fruits": [
          {
            "bad_name": "Banana"
          }
        ]
      }
    ]
  }
]

Now I want to rename the field bad_name to good_name.

[
  {
    "variants": [
      {
        "fruits": [
          {
            "good_name": "Banana"
          }
        ]
      }
    ]
  }
]

I tried first using $rename but that did not work:

db.collection.update({},
[
  {
    "$rename": {
      "variants.$.fruits.$.bad_name": "good_name"
    }
  }
])

https://mongoplayground.net/p/-I8ewTLuisT

Then I tried an overly complicated looking way I found which also did not work:

db.collection.update({},
[
  {
    $set: {
      "variants.fruits": {
        $map: {
          input: "$variants.fruits",
          in: {
            $mergeObjects: [
              "$$this",
              {
                fruits: {
                  $map: {
                    input: "$$this.fruits",
                    in: {
                      good_name: "$$this.bad_name"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
]) 

https://mongoplayground.net/p/f8EXddVOvVa

Is there any easy way to simply rename a field in a subdocument located in a deeply nested array?

Thanks for your help!


Solution

  • You should iterate the element in the variants array and in each variant element, you also required to iterate the element in the fruits array.

    Lastly, remove the bad_name field with $unset stage.

    db.collection.update({},
    [
      {
        $set: {
          variants: {
            $map: {
              input: "$variants",
              as: "v",
              in: {
                $mergeObjects: [
                  "$$v",
                  {
                    fruits: {
                      $map: {
                        input: "$$v.fruits",
                        in: {
                          $mergeObjects: [
                            "$$this",
                            {
                              good_name: "$$this.bad_name"
                            }
                          ]
                        }
                      }
                    }
                  }
                ]
              }
            }
          }
        }
      },
      {
        $unset: "variants.fruits.bad_name"
      }
    ])
    

    Demo @ Mongo Playground