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
CodePudding user response:
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.
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
( Afcourse Step 1 need to be executed first!!! )
CodePudding user response:
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.