Reputation: 53
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.
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' }, });
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); }) });
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 } }); }
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!
Upvotes: 4
Views: 1124
Reputation: 103305
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);
}
);
});
Upvotes: 1