This is a sample collection in which I want to update a user's posts. In fact, I want to operate a command similar to $push and $pop so that I can remove or add the userId from the likes array inside the posts array, this seems fairly simple but the catch is that I want to update the likes of a particular post matched by _id field of objects within posts array.
[
{
"_id": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"fullName": "user1",
"email": "[email protected]",
"password": "2ドルb10ドル$Yrs5H3mYrM8xLwWlek3K7uAs.EOLsXggj6wV7oSflPlPjo1ZkFem6",
"avatar": "https://avatars.dicebear.com/api/human/[email protected]",
"posts": [
{
"postContent": "sample 1",
"medias": [
"files/78560be22a25988c38ddafa0be7558f73713607a.jpeg"
],
"createdAt": {
"$date": "2021年09月07日T12:40:54.930Z"
},
"userId": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"authorName": "user1",
"avatar": "https://avatars.dicebear.com/api/human/[email protected]",
"likes": [],
"comments": [],
"_id": {
"$oid": "61375dd61c7d0a1a6e6005f3"
}
},
{
"postContent": "sample 2",
"medias": [
"files/5af7e5086e8dfb8af6c8e7bac3f2430a78d80ac1.jpeg",
"files/c01ed66cef55c876c8e7800aa5c820b9aeee7267.jpeg"
],
"createdAt": {
"$date": "2021年09月07日T12:42:01.142Z"
},
"userId": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"authorName": "user 2",
"avatar": "https://avatars.dicebear.com/api/human/[email protected]",
"likes": [],
"comments": [],
"_id": {
"$oid": "61375e191c7d0a1a6e6005f4"
}
}
],
"friendRequests": []
}
]
i.e, once a query is executed the likes array of the particular post (matched by _id) has to be updated with the userId (both userId and postId will be input in this case)
eg:
document.posts.likes = [61375acc1c7d0a1a6e6005f0, 61375acc1c7d0a1aasdfasgre3]
-
you want to push posts.userId in posts.like ?mohammad Naimi– mohammad Naimi2021年09月07日 14:26:32 +00:00Commented Sep 7, 2021 at 14:26
-
No read the last part... Likes array inside posts array objects should store id of users who liked the respective postsVishnu Mohan– Vishnu Mohan2021年09月07日 14:40:53 +00:00Commented Sep 7, 2021 at 14:40
1 Answer 1
There is no straight way to do this, you can try update with aggregation pipeline starting from MongoDB 4.2,
$mapto iterate look ofpostsarray$condto check if post id match then go to update part otherwise return same object$condto check if user id in likes array then go to remove part otehrwise add id inlikes$filterto iterate loop of likes array and remove user id$concatArraysadd user id inlikesarray$mergeObjectsto merge current object with updatedlikesarray field
let postId = { "$oid": "61375e191c7d0a1a6e6005f4" };
let userId = "61375dd61c7d0a1a6e6005f1";
db.collection.updateOne(
{ "posts._id": postId },
[{
"$set": {
"posts": {
$map: {
input: "$posts",
as: "p",
in: {
$cond: [
{ $eq: ["$$p._id", postId ] },
{
$mergeObjects: [
"$$p",
{
"likes": {
"$cond": [
{ $in: [userId, "$$p.likes"] },
{
$filter: {
input: "$$p.likes",
cond: { $ne: ["$$this", userId] }
}
},
{
"$concatArrays": ["$$p.likes", [userId]]
}
]
}
}
]
},
"$$p"
]
}
}
}
}
}]
)