4
votes

I'm trying building an application using MongoDB, Mongoose, JQuery, and Node.js. Whenever I try to add to an array within my Schema sometimes it will add that item several times.

Schema

This is my schema, I'm trying to add the my upvote and downvote arrays that keep track of users that voted by their id.


    var SuggestionSchema = new mongoose.Schema({
      title: String,
      content: String,
      link: String,
      upvote: [{
        user_id: {
        type: Schema.ObjectId,
        ref: 'User'
        }
      }],
      downvote: [{
        user_id: {
        type: Schema.ObjectId,
        ref: 'User'
        }
      }],
      user_id: {
        type: Schema.ObjectId,
        ref: 'User'
      },
      category_id: {
        type: Schema.ObjectId,
        ref: 'Category'
      },
    });

Route and Query

Here is my put route and query


    router.put('/:suggestion_id/downvote', function(req, res, next) {
      Suggestion.findByIdAndUpdate(
      req.params.suggestion_id,
      {$push: {"downvote": req.body}},
      function(err, suggestion) {
        res.json(suggestion);
      })
    });

Ajax Call with Jquery

This is my PUT request that is triggered on a click.


$('#downvote').click(function(){
    
    var user = {
        user_id: current_user._id
    }

    $.ajax({
        url: current_url + "suggestions/" + current_suggestion + '/downvote',
        type: 'PUT',
        data: user,
        success: function(data){
            //callback
        }
    });         

}

Results

Two other things to note:

The console will return:

Failed to load resource: net::ERR_EMPTY_RESPONSE

AND

Ultimately just clicking once sometimes results in 2 or 3 of the same user being pushed into the downvote array in the Schema. I put some safeguards on the front end that checks if the user has already voted, but it still seems to put through multiple times so I think it's a different issue. I believe I'm just approaching it wrong or missing something fundamental. I've only been coding for 6 months so I'm still learning. Thanks!

1
And do you see multiple requests happening against the server when this happens?Robert Moskal

1 Answers

1
votes

Instead of using the $push operator to push the user id object to the downvote array, use the $addToSet operator. This adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array. It only ensures that there are no duplicate items added to the set and does not affect existing duplicate elements. If the field is absent in the document to update, $addToSet creates the array field with the specified value as its element. So you final route will look like:

router.put('/:suggestion_id/downvote', function(req, res, next) {
    Suggestion.findByIdAndUpdate(
        req.params.suggestion_id,
        {$addToSet: {"downvote": req.body}},
        function(err, suggestion) {
            res.json(suggestion);
        }
    );
});