Attempting to replace a substring in an array of subdocuments

I’m attempting to replace a portion of a string in a nested array of objects. Essentially each object in the array has a “text” field, which contains a reference to a roaming fee. I’d like to change the text from roaming fee to transaction fee.

The result of my query is a little strange, it replaces the array of objects with an array of strings. The strings have the correct “transaction fee” text.

Would really appreciate some help with this one!

Query

db.collection.updateMany(
{ 'alt_text.text': { $regex: /Roaming Fee/ } },
[
    {
        $set: {
          alt_text: {
                $map: {
                   input: '$alt_text',
                   in: {
                        $replaceOne: {
                            input: '$$this.text',
                            find: 'Roaming',
                            replacement: 'Transaction'
                        }
                    }
                }
            }
        }
    }
]
)

Original Document

{ 
  "_id" : ObjectId("61683ffc6de6bb26d40f87b2"), 
  "last_updated" : ISODate("2021-10-14T14:32:10.699Z"), 
  "alt_text" : [
      {
          "language" : "en", 
          "text" : "$1.00 per hour\n$1.25 Roaming Fee"
      }, 
      {
          "language" : "fr", 
          "text" : "1,00 $ par heure\nFrais Roaming 1,25 $"
      }
  ], 
  "id" : "abcd"
}

Expected Output

{ 
  "_id" : ObjectId("61683ffc6de6bb26d40f87b2"), 
  "last_updated" : ISODate("2021-10-14T14:32:10.699Z"), 
  "alt_text" : [
      {
          "language" : "en", 
          "text" : "$1.00 per hour\n$1.25 Transaction Fee"
      }, 
      {
          "language" : "fr", 
          "text" : "1,00 $ par heure\nFrais de Transaction 1,25 $"
      }
  ], 
  "id" : "abcd"
}

It is not strange. It is what you asked. You asked to $map each object of the array alt_text with the respective $replaceOne which produce strings. Your in: expression has to look something like:

This is untested, but it is the general idea.

in: { 
  language: "$$this.language" ,
  text: { $replaceOne: {
                            input: '$$this.text',
                            find: 'Roaming',
                            replacement: 'Transaction'
                        } }
}
1 Like

Note that if you don’t know all the fields that might in inside the object in the array, you can use $mergeObjects to preserve existing fields while updating text field.

Asya

2 Likes

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.