Home > Software engineering >  Update nested array object value by replacing substring of that object property
Update nested array object value by replacing substring of that object property

Time:05-19

I have a following set of data in my mongodb collection called orders:

{
    "_id" : ObjectId("618e0e1b17687316dcdd6246"),
    "groupUID": "abc",
    "orderData" : {
        "charges" : {
            "total" : 18480.0,
            "subtotal" : 13980.0 
        },
        "items" : [ 
            {
                "name" : "Chocolate cookies",
                "imageURL": "domainURL2.com/cookies"
            },
            {
                "name" : "Chocolate muffins",
                "imageURL": "domainURL2.com/muffins"
            }
        ]
    }
}

Now I want to update the imageURL substring part of "domainURL2" to "domainURL1" field in every document of this collection. I have the following query so far:

db.orders.update( { "groupUID" : "abc" }, { "$set": { "orderData.items.$.imageURL":"myURL.com" } } )

I also have the query in javascript form but i want this to be in pure mongo query. So the query below will not do it for me unfortunately.

db.getCollection("orders").find({"groupUID" : "abc"}).forEach(function(aRow) {
    if (aRow.orderDetails !== undefined) {
    var updated = false;
        aRow.orderData.items.forEach(function(item) {

item.imageURL = item.imageURL.replace("eddress/", "noknok-app/");
        })
db.getCollection("orders").save(aRow);
    }
});

I want to update all record's imageURL field's substring part. I am unable to figure out the rest of the query. Can anyone please help me.

CodePudding user response:

My answer may look complex (Welcome for suggestion/improvement).

Work the update with Aggegration Pipeline.

  1. $set - Update orderData.items field.

    1.1. $map - Iterate orderData.items and returns new array.

    1.1.1. $mergeObjects - Merge current object and imageURL field from 1.1.1.1.

    1.1.1.1. $cond - With $regexMatch to find the imageURL starts with "domainURL2.com".

    1.1.1.2. If true, then replace "domainURL2.com" with "domainURL1.com".

    1.1.1.3. If false, remain existing value.

db.collection.update({
  "groupUID": "abc"
},
[
  {
    "$set": {
      "orderData.items": {
        $map: {
          input: "$orderData.items",
          in: {
            $mergeObjects: [
              "$$this",
              {
                imageURL: {
                  $cond: {
                    if: {
                      $regexMatch: {
                        input: "$$this.imageURL",
                        regex: "^domainURL2.com"
                      }
                    },
                    then: {
                      $concat: [
                        "domainURL1.com",
                        {
                          $arrayElemAt: [
                            {
                              $split: [
                                "$$this.imageURL",
                                "domainURL2.com"
                              ]
                            },
                            -1
                          ]
                        }
                      ]
                    },
                    else: "$$this.imageURL"
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Sample Mongo Playground

  • Related