skip to Main Content

I am trying to update the name of a key inside an object of an array and annoyed due to the inability to make the queries work. I have tried this How rename nested key in array of object in MongoDB? but I still get the same error I was getting earlier

Here is the document:

[
  {
  "accountCreation": [
      {
        "startDateTime": "",
        "endDateTime": "",
        "isDone": "Yes"
      }
    ]
  }
]

Here is my query:

db.collection.update({}, $rename:{
  "accountCreation.$.isDone":"done",
})

All I am trying to do is rename the isDone key to done. Note that this is just one of the many objects that have this key. I am trying to update all the occurences of the isDone key to done inside the accountCreation

Here is the error I am receiving:

fail to run update: write exception: write errors: [cannot use the part (accountCreation of accountCreation.isDone) to traverse the element

2

Answers


  1. Actually, the answers to the link you provided already stated that $rename does not work with array.

    Nevertheless, you could probably achieve your expected behaviour by using an aggregate with update. You will need to use $objectToArray and $arrayToObject to wrangle the objects if you have other fields.

    db.collection.update({},
    [
      {
        "$project": {
          accountCreation: {
            "$map": {
              "input": "$accountCreation",
              "as": "ac",
              "in": {
                "$objectToArray": "$$ac"
              }
            }
          }
        }
      },
      {
        "$project": {
          accountCreation: {
            "$map": {
              "input": "$accountCreation",
              "as": "ac",
              "in": {
                "$map": {
                  "input": "$$ac",
                  "as": "kv",
                  "in": {
                    "$cond": {
                      "if": {
                        $eq: [
                          "$$kv.k",
                          "isDone"
                        ]
                      },
                      "then": {
                        "k": "done",
                        "v": "$$kv.v"
                      },
                      "else": "$$kv"
                    }
                  }
                }
              }
            }
          }
        }
      },
      {
        "$project": {
          accountCreation: {
            "$map": {
              "input": "$accountCreation",
              "as": "ac",
              "in": {
                "$arrayToObject": "$$ac"
              }
            }
          }
        }
      }
    ])
    

    Here is the Mongo playground for your reference.

    Login or Signup to reply.
  2. This can be done in two steps(mongoDB 4.2+):

    Step 1: Add the new field "done"

    db.collection.update({
       "accountCreation": {
              $exists: true
          }
       },
       [
       {
         "$addFields": {
           accountCreation: {
             "$map": {
               "input": "$accountCreation",
               "as": "ac",
               "in": {
              $mergeObjects: [
              "$$ac",
              {
                "done": "$$ac.isDone"
              }
             ]
            }
          }
         }
       }
     }
    ],
    {
      multi: true
    })
    

    Explained:

    Add the field "Done"="$isDone" in all array elements where isDone is found.

    playground_step_1

    Step 2: Remove the old field "isDone":

      db.collection.update({
       "accountCreation.isDone": {
       "$exists": true
      }
     },
     {
      "$unset": {
        "accountCreation.$[x].isDone": true
     }
    },
    {
      arrayFilters: [
     {
      "x.isDone": {
        $exists: true
      }
    }
    ],
       multi: true
    })
    

    Explained:

    Define arrayFilter x and remove the old field "isDone" from all array elements where it is found

    playground_step_2

    ( Afcourse Step 1 need to be executed first!!! )

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search