For OP's MongoDB 4.0, we can do an aggregation to set the relevant fields:
trivial to update route
field
$map
to update children.parentRoute
Inside $map
in step 2,
3.1. do a $split
to break children.route
by /
characters into an array
3.2. do a $map
on the array to replace abc
with mno
by $cond
3.3. rejoin the replaced array into string with $replace
3.4. the resulting string will have heading '/', remove it by $ltrim
db.collection.aggregate([
{
$set: {
// input mno here
route: "mno",
children: {
"$map": {
"input": "$children",
"as": "c",
"in": {
_id: "$$c._id",
// input mno here
parentRoute: "mno",
currentRoute: "$$c.currentRoute",
route: {
"$ltrim": {
"input": {
"$reduce": {
"input": {
$map: {
input: {
$split: [
"$$c.route",
"/"
]
},
as: "r",
in: {
"$cond": {
"if": {
$eq: [
"$$r",
"abc"
]
},
"then": "mno",
"else": "$$r"
}
}
}
},
"initialValue": "",
"in": {
"$concat": [
"$$value",
"/",
"$$this"
]
}
}
},
"chars": "/"
}
}
}
}
}
}
}
])
finally do a JS update as $merge
or update with aggregation pipeline is not ready in MongoDB 4.0.
db.collection.aggregate([...]).forEach(result => {
db.collection.update({_id: result._id}, {$set: {children: result.children}})
})