2

I am struggling with avatar URL update in nested objects array persisted in MongoDB.

Avatar URL needs to be updated from "https://old.com/image.jpg" to "https://new.com/image.jpg"

The document structure is at the end of this post. I need to update the avatar in three places:

  1. organizer.avatar - it works (see below or visit Mongo playground-organizer avatar)
  2. meetings[].owner.avatar - similar issue found on StackOverflow, but it does not work because of different document structure (see below or visit Mongo playground-owner avatar)
  3. meetings[].participants[].avatar - I have not idea how to handle this.

Update organizer.avatar

It is pretty straightforward as you can see in Mongo playground- organizer avatar.

db.collection.update({},
[
  {
    "$set": {
      "organizer.avatar": {
        $replaceOne: {
          input: "$organizer.avatar",
          find: "https://old.com/",
          replacement: "https://new.com/"
        }
      }
    }
  }
])

Update meetings[].owner.avatar

It is similar to another issue reported on StackOverflow, but here avatar is nested inside the owner object. In this case, operator $mergeObjects does not work as I would expect, because it does not merge objects, but overrides it - see Mongo playground-owner avatar. How to fix this?

db.collection.update({},
[
  {
    "$set": {
      "meetings": {
        $map: {
          input: "$meetings",
          in: {
            $mergeObjects: [
              {
                owner: "$$this.owner"
              },
              {
                owner: {
                  avatar: {
                    $replaceOne: {
                      input: "$$this.owner.avatar",
                      find: "https://old.com/",
                      replacement: "https://new.com/"
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Update meetings[].participants[].avatar

When it comes to updating meetings[].participants[].avatar - do you have any idea how to handle this?

Example document:

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "eventName": "Welcome Event",
    "meetings": [
      {
        "owner": {
          "avatar": "https://old.com/dwight-schrute.png",
          "name": "Dwight Schrute"
        },
        "participants": [
          {
            "avatar": "https://old.com/kevin-malonoe.png",
            "name": "Kevin Malonoe"
          },
          {
            "avatar": "https://old.com/creed-bratton.png",
            "name": "Creed Bratton"
          }
        ]
      },
      {
        "owner": {
          "avatar": "https://old.com/jim-halpert.png",
          "name": "Jim Halpert"
        },
        "participants": [
          {
            "avatar": "https://old.com/pam-beesly.png",
            "name": "Pam Beesly"
          }
        ]
      }
    ],
    "organizer": {
      "avatar": "https://old.com/michale-scott.png",
      "name": "Michael Scott"
    }
  }
]

1 Answer 1

2

Your update query should consist of these concepts to achieve the expected result:

  1. Merge iterated object.

  2. Update the iterated owner's avatar.

  3. Update the element's avatar in the iterated object's participants array.

db.collection.update({},
[
  {
    "$set": {
      "meetings": {
        $map: {
          input: "$meetings",
          in: {
            $mergeObjects: [
              "$$this",
              {
                owner: {
                  $mergeObjects: [
                    "$$this.owner",
                    {
                      avatar: {
                        $replaceOne: {
                          input: "$$this.owner.avatar",
                          find: "https://old.com/",
                          replacement: "https://new.com/"
                        }
                      }
                    }
                  ]
                }
              },
              {
                participants: {
                  $map: {
                    input: "$$this.participants",
                    as: "p",
                    in: {
                      $mergeObjects: [
                        "$$p",
                        {
                          avatar: {
                            $replaceOne: {
                              input: "$$p.avatar",
                              find: "https://old.com/",
                              replacement: "https://new.com/"
                            }
                          }
                        }
                      ]
                    }
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

Demo @ Mongo Playground

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, it works like a charm. I've fixed a typo in one place (name -> avatar) in your Demo @ Mongo Playground and added update for organizer avatar - latest version: Updated Demo @ Mongo Playground: mongoplayground.net/p/CX7Lm7qjI_i

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.