1

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": "$2b$10$Yrs5H3mYrM8xLwWlek3K7uAs.EOLsXggj6wV7oSflPlPjo1ZkFem6",
    "avatar": "https://avatars.dicebear.com/api/human/[email protected]",
    "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/[email protected]",
        "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/[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]
2
  • you want to push posts.userId in posts.like ? Commented 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 posts Commented Sep 7, 2021 at 14:40

1 Answer 1

1

There is no straight way to do this, you can try update with aggregation pipeline starting from MongoDB 4.2,

  • $map to iterate look of posts array
  • $cond to check if post id match then go to update part otherwise return same object
  • $cond to check if user id in likes array then go to remove part otehrwise add id in likes
  • $filter to iterate loop of likes array and remove user id
  • $concatArrays add user id in likes array
  • $mergeObjects to merge current object with updated likes array 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"
            ]
          }
        }
      }
    }
  }]
)

Playground

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.