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:
organizer.avatar
- it works (see below or visit Mongo playground-organizer avatar)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)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"
}
}
]
Your update query should consist of these concepts to achieve the expected result:
Merge iterated object.
Update the iterated owner
's avatar
.
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/"
}
}
}
]
}
}
}
}
]
}
}
}
}
}
])