Swapnil Sourabh
Swapnil Sourabh

Reputation: 519

Mongo4.0 How to concatenate two existing fields into one in Mongo

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

Answers (1)

ray
ray

Reputation: 15287

For OP's MongoDB 4.0, we can do an aggregation to set the relevant fields:

  1. trivial to update route field

  2. $map to update children.parentRoute

  3. 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

Related Questions