'Move a dynamic number of array elements from one collection's to another collection in MongoDB
I'm working on a Discord Bot but this question is about the service-end I've created for the bot. The scenario I'm working on is as follows, whenever a user deletes their account all of the images uploaded by said user will be removed from the GUILDS collection and placed in the DELETED_CONTENT collection. Specifically, a user's image data will be removed from a GUILD's image_pool array and placed in a respective DELETED_CONTENT image_pool array.
The number of images varies by user and the number of GUILDS that a user is associated also varies. image_pool data is dynamic so overwriting that would be nuanced to maintain state, whereas the rest of a GUILD's data is static. What I'm looking to achieve below assuming 'jeskoston' deletes account. I've added a comment to their username for clarity.
Current GUILDS (collection)
{
"_id" : ObjectId("61b3db8b965d8d06da643edd"),
"preferred_locale" : "en-US",
"nsfw" : false,
"installed_by_id" : "795864504197578834",
"installed_by_username" : "philjackson",
"image_pool" : [
{
"_id" : ObjectId("61eb74edaa9c4c0f53cbff67"),
"date_uploaded" : "2022-01-21T19:07:25-08:00",
"uploaded_by_discord_username" : "jeskoston <-- WILL DELETE ACCOUNT",
"uploaded_by_id" : "619dadc90565852231712345",
"image_title" : "Jordan",
"image_url" : "/uploads/925819329911062589/1642820844573IMG-4148.JPG",
"likes" : null,
"flags" : 0,
"nsfw" : null
},
{
"_id" : ObjectId("61eb74edaa9c4c0f53cbfe88"),
"date_uploaded" : "2022-01-21T19:07:25-08:00",
"uploaded_by_discord_username" : "andydiscord",
"uploaded_by_id" : "619dadc90565852231771649",
"image_title" : "Pippen",
"image_url" : "/uploads/825519329911062589/5442820844573IMG-1111.png",
"likes" : null,
"flags" : 0,
"nsfw" : null
}
],
"install_date" : "2021-12-10T22:58:19.504Z",
"discord" : {
"id" : "945819329911062589",
"owner_id" : "795864504197577734",
"system_channel_id" : "888819329911062592",
"name" : "bulls"
}
},
{
"_id" : ObjectId("61eb9a0cbcbea4139ea17123"),
"preferred_locale" : "en-US",
"nsfw" : false,
"installed_by_id" : "795864504197578834",
"installed_by_username" : "georgekarl",
"image_pool" : [
{
"_id" : ObjectId("61eb74edaa9c4c0f53cbfe90"),
"date_uploaded" : "2022-01-21T19:09:30-08:00",
"uploaded_by_discord_username" : "jeskoston <-- WILL DELETE ACCOUNT",
"uploaded_by_id" : "619dadc90565852231712345",
"image_title" : "Malone",
"image_url" : "/uploads/995519329911062100/7842820844573IMG-4000.jpg",
"likes" : null,
"flags" : 0,
"nsfw" : null
}
],
"install_date" : "2022-01-22T05:45:48.011Z",
"discord" : {
"id" : "549483811550042074",
"owner_id" : "792864524197578834",
"system_channel_id" : "849421811440042077",
"name" : "jazz"
}
}
Current DELETED_CONTENT (collection):
{
"_id" : ObjectId("88b3db8b965d8d06da643p09"),
"preferred_locale" : "en-US",
"nsfw" : false,
"installed_by_id" : "795864504197578834",
"installed_by_username" : "philjackson",
"guild_uninstalled": false,
"image_pool" : [
{
"_id" : ObjectId("61eb74edaa9c4c0f53cbfk3p"),
"date_uploaded" : "2022-01-21T19:07:25-08:00",
"date_deleted" : "2022-01-25T01:07:45-08:00",
"uploaded_by_discord_username" : "andrewdiscord",
"uploaded_by_id" : "619dadc90565852231771659",
"image_title" : "Rodman",
"image_url" : "/uploads/925819329911062589/1232820844573IMG-4148.JPG",
"likes" : null,
"flags" : 0,
"nsfw" : null,
"date_deleted" : "2022-01-22T19:09:25-08:00",
},
],
"install_date" : "2021-12-10T22:58:19.504Z",
"discord" : {
"id" : "945819329911062589",
"owner_id" : "795864504197577734",
"system_channel_id" : "888819329911062592",
"name" : "bulls"
}
},
{
"_id" : ObjectId("61eb9a0cbcbea4139ea17789"),
"preferred_locale" : "en-US",
"nsfw" : false,
"installed_by_id" : "795864504197578834",
"installed_by_username" : "georgekarl",
"guild_uninstalled": false,
"image_pool":[{
"_id" : ObjectId("888b74edaa9c4c0f53cbff45"),
"date_uploaded" : "2022-02-23T12:07:11-08:00",
"date_deleted" : "2022-02-24T11:02:01-08:00",
"uploaded_by_discord_username" : "jakediscord",
"uploaded_by_id" : "619dadc9056585223175461f",
"image_title" : "Stockton",
"image_url" : "/uploads/925819329911062589/1232820844573IMG-4148.JPG",
"likes" : null,
"flags" : 0,
"nsfw" : null,
"date_deleted" : "2022-03-22T04:09:00-08:00",
}
],
"install_date" : "2022-01-22T05:45:48.011Z",
"discord" : {
"id" : "549483811550042074",
"owner_id" : "792864524197578834",
"system_channel_id" : "849421811440042077",
"name" : "jazz"
}
}
Desired GUILDS (collection) after user jeskoston deletes their account:
{
"_id" : ObjectId("61b3db8b965d8d06da643edd"),
"preferred_locale" : "en-US",
"nsfw" : false,
"installed_by_id" : "795864504197578834",
"installed_by_username" : "philjackson",
"image_pool" : [
{
"_id" : ObjectId("61eb74edaa9c4c0f53cbfe88"),
"date_uploaded" : "2022-01-21T19:07:25-08:00",
"uploaded_by_discord_username" : "andydiscord",
"uploaded_by_id" : "619dadc90565852231771649",
"image_title" : "Pippen",
"image_url" : "/uploads/825519329911062589/5442820844573IMG-1111.png",
"likes" : null,
"flags" : 0,
"nsfw" : null
}
],
"install_date" : "2021-12-10T22:58:19.504Z",
"discord" : {
"id" : "945819329911062589",
"owner_id" : "795864504197577734",
"system_channel_id" : "888819329911062592",
"name" : "bulls"
}
},
{
"_id" : ObjectId("61eb9a0cbcbea4139ea17123"),
"preferred_locale" : "en-US",
"nsfw" : false,
"installed_by_id" : "795864504197578834",
"installed_by_username" : "georgekarl",
"image_pool" : [],
"install_date" : "2022-01-22T05:45:48.011Z",
"discord" : {
"id" : "549483811550042074",
"owner_id" : "792864524197578834",
"system_channel_id" : "849421811440042077",
"name" : "jazz"
}
}
Desired DELETED_CONTENT (collection) after user jeskoston deletes their account:
{
"_id" : ObjectId("88b3db8b965d8d06da643p09"),
"preferred_locale" : "en-US",
"nsfw" : false,
"installed_by_id" : "795864504197578834",
"installed_by_username" : "philjackson",
"guild_uninstalled": false,
"image_pool" : [
{
"_id" : ObjectId("61eb74edaa9c4c0f53cbff67"),
"date_uploaded" : "2022-01-21T19:07:25-08:00",
"date_deleted" : "2022-01-22T19:09:25-08:00",
"uploaded_by_discord_username" : "andrewdiscord",
"uploaded_by_id" : "619dadc90565852231771659",
"image_title" : "Rodman",
"image_url" : "/uploads/925819329911062589/1232820844573IMG-4148.JPG",
"likes" : null,
"flags" : 0,
"nsfw" : null,
},
{
"_id" : ObjectId("61eb74edaa9c4c0f53cbff67"),
"date_uploaded" : "2022-01-21T19:07:25-08:00",
"date_deleted" : "2022-01-26T07:09:51-08:00",
"uploaded_by_discord_username" : "jeskoston <-- ACCT DELETED",
"uploaded_by_id" : "619dadc90565852231712345",
"image_title" : "Jordan",
"image_url" : "/uploads/925819329911062589/1642820844573IMG-4148.JPG",
"likes" : null,
"flags" : 0,
"nsfw" : null
}
],
"install_date" : "2021-12-10T22:58:19.504Z",
"discord" : {
"id" : "945819329911062589",
"owner_id" : "795864504197577734",
"system_channel_id" : "888819329911062592",
"name" : "bulls"
}
},
{
"_id" : ObjectId("61eb9a0cbcbea4139ea17789"),
"preferred_locale" : "en-US",
"nsfw" : false,
"installed_by_id" : "795864504197578834",
"installed_by_username" : "georgekarl",
"guild_uninstalled": false,
"image_pool":[{
"_id" : ObjectId("888b74edaa9c4c0f53cbff45"),
"date_uploaded" : "2022-02-21T15:07:11-08:00",
"date_deleted" : "2022-03-02T04:09:00-08:00",
"uploaded_by_discord_username" : "jakediscord",
"uploaded_by_id" : "619dadc9056585223175461f",
"image_title" : "Stockton",
"image_url" : "/uploads/925819329911062589/1232820844573IMG-4148.JPG",
"likes" : null,
"flags" : 0,
"nsfw" : null,
},
{
"_id" : ObjectId("61eb74edaa9c4c0f53cbfe90"),
"date_uploaded" : "2022-01-21T19:09:30-08:00",
"date_deleted" : "2022-23-22T04:09:00-08:00",
"uploaded_by_discord_username" : "jeskoston <-- ACCT DELETED",
"uploaded_by_id" : "619dadc90565852231712345",
"image_title" : "Malone",
"image_url" : "/uploads/995519329911062100/7842820844573IMG-4000.jpg",
"likes" : null,
"flags" : 0,
"nsfw" : null
}
],
"install_date" : "2022-01-22T05:45:48.011Z",
"discord" : {
"id" : "549483811550042074",
"owner_id" : "792864524197578834",
"system_channel_id" : "849421811440042077",
"name" : "jazz"
}
}
My strategy thus far has been to #1 pull a user's images from the GUILDS collection but before doing that #2 copy data to push to the DELETED_CONTENT collection.
I have #1 finished
For #2 I have a query that collects a user's image data and adds a date_deleted timestamp to each image. I also include other GUILD data in query. I only return guild entries where a user has images posted.
('GUILDS').aggregate([
{
$project:
{
discord:1,
install_date:1,
installed_by_id:1,
installed_by_username:1,
preferred_locale:1,
nsfw:1,
guild_deleted:1,
user_images:
{
$filter:
{
input:"$image_pool",
as: "image",
cond:{ $eq: ["$$image.uploaded_by_id",'619dadc90565852231771659'] }
}
}
}
},
{
$addFields: {
guild_deleted:false,
"user_images":{
$map:{
input: "$user_images",
as:"image",
in:{
_id:"$$image._id",
date_deleted: "$$NOW",
date_uploaded:"$$image.date_uploaded",
uploaded_by_discord_username:"$$image.uploaded_by_discord_username",
uploaded_by_id:"$$image.uploaded_by_id",
image_title:"$$image.image_title",
image_url:"$$image.image_url",
likes:"$$image.likes",
flags:"$$image.flags",
nsfw:"$$image.nsfw"
}
}
}
}
},
{
$match:{ 'user_images.0':{ $exists: true } }
}
])
I retrieve user data based on an images 'uploaded_by_id' value. I include static guild info in the event I have to upsert the whole document, user_images are a user's images from a GUILD's respective image_pool(s).
I want to be able to move this data without looping calls to the database. I've tried to use bulkWrite but have had no luck, I cannot find a concrete example that has a use-case for a dynamic number of entries. I've attempted to create a dynamic string for bulkWrite with no luck. I've also attempted to use $merge but I'm having trouble with the pipeline operators under whenMatched field.
Maybe my entire approach is off? I will spare my other attempts since this has gotten long. I'm not sure if anyone can help, but any attempt would be appreciated.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
