skip to Main Content

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[].avatarI 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[].avatardo 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"
    }
  }
]

2

Answers


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

    Login or Signup to reply.
  2. Simple you can directly update any property of all element of and array by accessing arrayName.property

    For Example meetings.owner.avatar will update owner.avatar property of all element available in meetings array

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

    MongoPlayGround Demo

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search