Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate through Mongoose results to update value

I am somewhat new to this, so if I am on the completely wrong track feel free to let me know.

I have the following post schema.

var Post = new Schema( {
    description: {
        type: String,
        default: '',
        required: 'Please type a description',
        trim: true
    },
    likeCount: {
        type: Number,
        default: 0
    },
    url: {
        type: String,
        default: '',
        required: 'Unable to find photo',
        trim: true
    },
    created: {
        type: Date,
        default: Date.now
    },
    user: {
        type: Schema.ObjectId,
        ref: 'User',
        required: 'Unable to verify user'
    },
    comments: {
        type: [Comment]
    },
    //Dynamically added values
    hasLiked: {
        type: Boolean
    }
});

And the following Like schema

var Like = new Schema({
    created: {
        type: Date,
        default: Date.now
    },
    user: {
        type: Schema.ObjectId,
        ref: 'User'
    },
    post: {
        type: Schema.ObjectId,
        ref: 'Post'
    }
});

When I show a user a list of posts I need to indicate whether they have previously "liked" a post, so I am trying to pull the posts, then iterate through them to determine if the person has liked it and update the value in the Post. I'm not getting any errors, but it's also not updating the hasLiked value. I put the hasLiked value into my Mongoose model because I can't just add a value on the fly before returning my results. I don't store an actual value for that in the DB because it would obviously be different for every person that viewed the post.

exports.list = function(req, res) {
    Post.find().sort('-created').populate('user', 'displayName')

        .exec(function (err, posts) {
        if (err) {
            return res.status(400).send({
                message: errorHandler.getErrorMessage(err)
            });
        } else {

            for (var i = 0; i < posts.length; i++) {

                Like.find({ 'post': posts[i]._id, 'user': req.user.id }).exec(function (err, like) {
                    if (err) {
                        return res.status(400).send({
                            message: errorHandler.getErrorMessage(err)
                        });
                    } else {
                        if (like.length == 0)
                            posts[i].hasLiked = false;
                        else
                            posts[i].hasLiked = true;
                    }

                });

            }
            res.jsonp(posts);
        }
    });
};
like image 440
Jhorra Avatar asked Oct 21 '25 15:10

Jhorra


1 Answers

Node is async language. So your mistake here is that when you query to find if the user liked the post:

Like.find({ 'post': posts[i]._id, 'user': req.user.id }).exec(function (err, like)

the answer will return after you return the answer to the client. In other words, line res.jsonp(posts); performed before the answer from mongo returned and enters to the callback. Thats why it isn't working for you.

To handle with async methods, I suggest you to use a third-party library, such as async or q. Here is one solution for you with Q library:

var Q = require('q');

var promises = [];
posts.forEach(function(post) {
  promise = Q(Like.find({ 'post': post._id, 'user': req.user.id }).exec())
    .then(
      function(like) {
          if (like.length == 0)
                post.hasLiked = false;
          else
                post.hasLiked = true;
          }
      }  
      ,function(err) {
         //handle error
    });
})

Q.all(promises)
  .then(function() {
      return res.jsonp(posts);
  });
like image 63
yyarden Avatar answered Oct 23 '25 04:10

yyarden



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!