1

I'm a newbie in to node.js and mongodb. Im using express for rest-api.

I'm trying to create an API where user can post and like. I'm able to create post API and the issue is with like API where the user can click the like button and it will be counted and when he clicks the like button again it will take as unlike and update the same in the backend server (express and mongodb) in my case.

Schema Definition

module.exports = mongoose.model('posts', new Schema({ 
    post: { type: String, required: true },
    date: { type: Date, required: true, default: moment.now() },
    author: { type: String, required: true },
    authorId: {type: String, required: true},
    likes: {type: Object, required: true, default: []},
    likesCount: { type: Number, required: true, default: 0},
    dislikes: { type: Object, required: true, default: [] },
    dislikesCount: { type: Number, required: true, default: 0 },
    comments: { type: Object, required: true, default: [] },
    commentsCount: { type: Number, required: true, default: 0 }
}, { timestamps : { createdAt: 'created_at' , updatedAt: 'updated_at' } }));

Code:

    router.post('/post/likes', function(req, res) {
    if (!_.isEmpty(req.body.postId) && !_.isEmpty(req.body.user) && !_.isEmpty(req.body.userId)) {

        //Finding the post by Id
        Posts.findById(req.body.postId, function(err, posts) {

            if (err) {
                return res.send(500).json({
                    success: false,
                    msg: err
                });
            }

            if (posts !== null) {
                var user = {
                    userId: req.body.userId,
                    user: req.body.user
                };
                //Returns the matched obj if true
                //Returns undefined if false
                var alreadyLiked = _.find(posts.likes, function(obj) {
                    if (obj.userId === user.userId && obj.user === user.user) {
                        return true;
                    } else {
                        return false;
                    }
                });


                if (alreadyLiked === undefined) {
                    posts.likes.push(user);
                    posts.likesCount = posts.likes.length;

                    var updatedPost = new Posts(posts);
                    updatedPost.save(function(err, data) {
                        if (err) {
                            return err;
                        }
                        res.status(200).send({
                            success: true,
                            data: data,
                            message: 'You have liked the post!'
                        });

                    });

                } else {
                    //Removing the already liked user object from posts.likes
                    posts.likes = _.without(posts.likes, _.findWhere(posts.likes, user));
                    posts.likesCount = posts.likes.length;

                    posts.markModified('likesCount');
                    var reupdated = new Posts(posts);
                    reupdated.save(function(err, data) {
                        if (err) {
                            return err;
                        }
                        res.status(200).send({
                            success: true,
                            data: data,
                            message: 'You have unliked the post!'
                        });

                    });

                }
            } else {
                res.status(200).send({
                    success: false,
                    message: 'No post found!'
                });
            }


        });
    } else {
        res.status(400).send({
            success: false,
            message: 'Bad request value'
        });
    }
});

The issue is when I like the post for first time it works perfect and returns the expected response.

img: liked-response-img

when i unlike the post by calling the same API it returns some unexpected result. The user who unliked is removed from the likes property but the count still remains '1' as shown in img below. I can't figure out why? Can someone please point out where and what I'm doing wrong. Thanks in advance!

img: unliked-response-img

Taha Md
  • 21
  • 2
  • 5

1 Answers1

1

how about just making posts.save() or posts.save().exec() instead of creating a new "copied" post and saving that.

Tobias Fuchs
  • 910
  • 5
  • 8
  • It worked for me! thanks , between can I know the reason why it was failing when i created an instance of the `Post` schema and saved it anyhow it updated the likes object but the count remained the same – Taha Md Mar 16 '18 at 14:40
  • (sry for the late response... wasnt working last week) The reason why it fails is that you pass a entire `Post` object inside the constructor of `updatedPost` and this gives a duplicate key/id error (not thrown). Your `posts` Object is a Instance of `Model` and the constructor requires a `Object` (this doesnt mean your solutions wouldnt work in theory.) – Tobias Fuchs Mar 20 '18 at 10:01
  • Ah and btw your code looks pretty crappy in seight of security (no offense). But i can tell you if you will ever use that code in a productive enviroment it will be cracked in less than a minute. 1. There is no Auth-proof (so you can just fake your identity) 2. There is no CSRF prevention so the code is weak anyway 3. The user get commited via Post body (overwriteable) – Tobias Fuchs Mar 20 '18 at 10:05
  • I know the code is crappy as Iam a naive user to express and mongoose. Iam learning things over time. – Taha Md Mar 26 '18 at 11:48