Reputation: 519
I am bound to use Mongo4.0.
I have a nested object.
{
_id:1,
route:'abc',
children:[
{
_id:2,
parentRoute:'abc',
currentRoute:'xyz',
route:'abc/xyz'
}]
}
Suppose for _id:1, if route is updated from 'abc' to 'mno' , then all children should update their parentRoute and route.
{
_id:1,
route:'mno',
children:[
{
_id:2,
parentRoute:'mno',
currentRoute:'xyz',
route:'mno/xyz'
}]
}
Feel free to suggest a different way!! I even thought of Regex $replaceOne, but again I am having difficulty with Mongo4.0 implementation.
Upvotes: 0
Views: 69
Reputation: 15287
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}})
})
Upvotes: 2