Mongodb 嵌套数组更新查询
Mongodb nested array update query
这是一个示例集合,我想在其中更新用户的 post。其实我想操作一个类似于$push
和$pop
的命令,这样我就可以在posts数组里面的likes数组中删除或添加userId,这看起来很简单但是问题是我想更新与 posts
数组中对象的 _id
字段匹配的特定 post 的 likes
。
[
{
"_id": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"fullName": "user1",
"email": "user1@gmail.com",
"password": "b$Yrs5H3mYrM8xLwWlek3K7uAs.EOLsXggj6wV7oSflPlPjo1ZkFem6",
"avatar": "https://avatars.dicebear.com/api/human/vishnu@gmail.com.svg",
"posts": [
{
"postContent": "sample 1",
"medias": [
"files/78560be22a25988c38ddafa0be7558f73713607a.jpeg"
],
"createdAt": {
"$date": "2021-09-07T12:40:54.930Z"
},
"userId": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"authorName": "user1",
"avatar": "https://avatars.dicebear.com/api/human/vishnu@gmail.com.svg",
"likes": [],
"comments": [],
"_id": {
"$oid": "61375dd61c7d0a1a6e6005f3"
}
},
{
"postContent": "sample 2",
"medias": [
"files/5af7e5086e8dfb8af6c8e7bac3f2430a78d80ac1.jpeg",
"files/c01ed66cef55c876c8e7800aa5c820b9aeee7267.jpeg"
],
"createdAt": {
"$date": "2021-09-07T12:42:01.142Z"
},
"userId": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"authorName": "user 2",
"avatar": "https://avatars.dicebear.com/api/human/user2@gmail.com.svg",
"likes": [],
"comments": [],
"_id": {
"$oid": "61375e191c7d0a1a6e6005f4"
}
}
],
"friendRequests": []
}
]
即,一旦执行查询,特定 post 的 likes
数组(由 _id
匹配)必须使用 userId 更新(userId 和 post在这种情况下将输入 Id)
例如:
document.posts.likes = [61375acc1c7d0a1a6e6005f0, 61375acc1c7d0a1aasdfasgre3]
没有直接的方法可以做到这一点,你可以尝试 update with aggregation pipeline 从 MongoDB 4.2,
$map
迭代 posts
数组 的外观
$cond
检查 post id 是否匹配然后去更新部分否则 return 相同的对象
$cond
检查用户 ID 是否在 likes 数组中然后去删除部分 otehrwise 在 likes
中添加 id
$filter
迭代 likes 数组的循环并删除用户 id
$concatArrays
在likes
数组中添加用户id
$mergeObjects
将当前对象与更新后的 likes
数组字段合并
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"
]
}
}
}
}
}]
)
这是一个示例集合,我想在其中更新用户的 post。其实我想操作一个类似于$push
和$pop
的命令,这样我就可以在posts数组里面的likes数组中删除或添加userId,这看起来很简单但是问题是我想更新与 posts
数组中对象的 _id
字段匹配的特定 post 的 likes
。
[
{
"_id": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"fullName": "user1",
"email": "user1@gmail.com",
"password": "b$Yrs5H3mYrM8xLwWlek3K7uAs.EOLsXggj6wV7oSflPlPjo1ZkFem6",
"avatar": "https://avatars.dicebear.com/api/human/vishnu@gmail.com.svg",
"posts": [
{
"postContent": "sample 1",
"medias": [
"files/78560be22a25988c38ddafa0be7558f73713607a.jpeg"
],
"createdAt": {
"$date": "2021-09-07T12:40:54.930Z"
},
"userId": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"authorName": "user1",
"avatar": "https://avatars.dicebear.com/api/human/vishnu@gmail.com.svg",
"likes": [],
"comments": [],
"_id": {
"$oid": "61375dd61c7d0a1a6e6005f3"
}
},
{
"postContent": "sample 2",
"medias": [
"files/5af7e5086e8dfb8af6c8e7bac3f2430a78d80ac1.jpeg",
"files/c01ed66cef55c876c8e7800aa5c820b9aeee7267.jpeg"
],
"createdAt": {
"$date": "2021-09-07T12:42:01.142Z"
},
"userId": {
"$oid": "61375acc1c7d0a1a6e6005f0"
},
"authorName": "user 2",
"avatar": "https://avatars.dicebear.com/api/human/user2@gmail.com.svg",
"likes": [],
"comments": [],
"_id": {
"$oid": "61375e191c7d0a1a6e6005f4"
}
}
],
"friendRequests": []
}
]
即,一旦执行查询,特定 post 的 likes
数组(由 _id
匹配)必须使用 userId 更新(userId 和 post在这种情况下将输入 Id)
例如:
document.posts.likes = [61375acc1c7d0a1a6e6005f0, 61375acc1c7d0a1aasdfasgre3]
没有直接的方法可以做到这一点,你可以尝试 update with aggregation pipeline 从 MongoDB 4.2,
$map
迭代posts
数组 的外观
$cond
检查 post id 是否匹配然后去更新部分否则 return 相同的对象$cond
检查用户 ID 是否在 likes 数组中然后去删除部分 otehrwise 在likes
中添加 id
$filter
迭代 likes 数组的循环并删除用户 id$concatArrays
在likes
数组中添加用户id$mergeObjects
将当前对象与更新后的likes
数组字段合并
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"
]
}
}
}
}
}]
)