1

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 2

3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

thanks for taking a look, i noticed that aggregate is not updating but just giving the edited response as an output. Because when I do a db.collection.find({)) to verify, it shows the isDone key again
@boomchickawawa sorry my bad. updated the answer to change back to use update
this is wiping out the other fields that present in the document and returning just the accountCreation array with the updated name when I do a db.collection.find({})
@boomchickawawa you should have stated that your accountCreation object contains other fields at the start. Nevertheless, updated the answer to do it in a more generic way.
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.