0

I am implementing an upvote (and downvote) system for users using node.js and mongoose mongodb, this is the logic:

    if (req.body.vote === 'up') {
        Posts.bulkWrite([
            {
                updateOne: {
                    filter: {
                        "_id": req.params.postId,
                        "votes.up": req.user._id 
                    },
                    update: {
                        $pull: { "votes.up": req.user._id },
                        $inc: { "upvoteCount": -1 }
                    }
                }
            },
            {
                updateOne: {
                    filter: {
                        "_id": req.params.postId,
                        "votes.up": { $ne: req.user._id },
                        "votes.down": req.user._id
                    },
                    update: {
                        $push: { "votes.up": req.user._id },
                        $inc: { "upvoteCount": 1, "downvoteCount": -1 },
                        $pull: { "votes.down": req.user._id }
                    }
                }
            },
            {
                updateOne: {
                    filter: {
                        "_id": req.params.postId,
                        "votes.up": { $ne: req.user._id }
                    },
                    update: {
                        $push: { "votes.up": req.user._id },
                        $inc: { "upvoteCount": 1 }
                    }
                }
            }
        ])
   }

the clear problem is that, in this case, if the user upvotes, it works, but then when trying to remove the upvote, via clicking the upvote button again, it is initially removed by the first update, but then added again because the third update sees the already modified document, meaning it updates it twice, I would like to limit it to only one modification. I thought of using a counter, but where do I put the if..? There might be a great architectural problem with this logic.

I am quite new to this, any advice/solution is appreciated.

Mannaroth
  • 470
  • 5
  • 13
  • I think you're missing the point here. If you looked at a page on stackoverflow ( you cannot see this sort of thing at 8 rep because you cannot upvote ) but it will actually show me if I have already upvoted on a post. This is because out the the big array of votes ( if stackoverflow did such a thing ) it returned "just my vote" to me along with the overall total. So I already know from an API point of view if I need to remove an existing vote or not. – Neil Lunn May 21 '18 at 07:50
  • Wrote more on this a long time ago [How to Model a “likes” voting system with MongoDB](https://stackoverflow.com/q/28006521/2313887). Talks about the same thing. You don't need to test to "remove", and you simply just do it. – Neil Lunn May 21 '18 at 07:51
  • @NeilLunn, yes, but I want to allow users to remove their upvotes, I already have it in place on my client-side for the users to see existing upvotes, but I think there will be cases where they want to remove it, but it is optional to leave it out, haha, I actually did find your answer, it helped me a lot, thanks for that, and thanks for this, I guess I missed something, I will look into it again – Mannaroth May 21 '18 at 07:59
  • Well removal is a "separate" action isn't it? That's the point. If you know you have not voted then vote, but by all means check the vote is there and don't add again. If you remove the vote, then remove it and by all means look to see if it's there, in order to decrease the count.You can do a "swap" but the success needs to be certain you are going up/down and not voted in any other array. But they probably should be separate actions. It's kind of broad but fairly logical when you think through it. – Neil Lunn May 21 '18 at 08:03

0 Answers0