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
  • $concatArrayslikes数组中添加用户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"
            ]
          }
        }
      }
    }
  }]
)

Playground