0

I have a label schema:

var labelSchema = mongoose.Schema({
   name: String,
   desc: String,
   postIds: [mongoose.Schema.ObjectId],
   removed: { type: Boolean, default: false }
})

I want to update postIds array when a label is assigned to a post, so I do in my update post request:

Label.update({'_id': { $in: post.labelIds }}, {$addToSet: {postIds:req.body.id}}, {multi: true})

Where post.labelIds is an array of label ids. I've tested the query with find() method and it works fine, it finds all the labels. However when I check the database for updated records, no label is updated.

When I do a console.log of post.LabelIds before the update command, it returns:

[ 'uniqueidhere', 'anotheruniqidthere' ]

and req.body.id

uniqueidhere

So the ids are there, but somehow the update doesn't work.

emil.c
  • 1,987
  • 2
  • 26
  • 46
  • Try wrapping the ids in `mongoose.Schema.ObjectId` – chridam Oct 15 '15 at 10:56
  • When I tried it in mongodb shell with ObjectId() wrapped around it it worked, which is great. However, how am I supposed to wrap around each element in the array with ObjectId()? – emil.c Oct 15 '15 at 11:14
  • If the label ids are hex strings then there's no need to cast them to ObjectId's, what I meant is casting the `req.body.id` values to ObjectId's like `var mongoose = require('mongoose'); var postId = mongoose.Types.ObjectId(req.body.id);` then use it in your update `$addToSet: {postIds: postId}` – chridam Oct 15 '15 at 11:21
  • I see what you mean, I've tried to update query without ObjectId() around it in mongodb shell and it didn't find anything. After you suggested wrapping ObjectId() around it, it found the labels and updated them accordingly and I didn't have to wrap ObjectId around the values in postIds. So I don't think there's a problem. I've also tried the mongoose = require(.... you're suggesting, however there was a casting error in console. – emil.c Oct 15 '15 at 11:23

1 Answers1

1

After a few hours spend trying to find out where the error was and why it wasn't updating the database, I found out it actually did update the database. The problem was that I was checking the update in mongo shell and after I updated it over nodejs post request, it didn't appear in the shell as updated. However when I console.log() the labels, it was updated. So I investigated the problem further and I found out that the the problem wasn't the mongo shell, but incorrect usage of mongoose command update. I was missing the callback argument. After adding the callback function, the data were updated in the mongo shell immediately.

So instead of doing:

Label.update({'_id': { $in: post.labelIds }}, {$addToSet: {postIds:req.body.id}}, {multi: true})

It mustn't be forgotten to add callback:

Label.update({'_id': { $in: post.labelIds }}, {$addToSet: {postIds:req.body.id}}, {multi: true}, function(err, affected) {
   if(err)
      console.log(err)
   else
      console.log(affected)
      // After successful update, redirect here to another page...

Or as duplicate answer suggests running exec():

Label.update({'_id': { $in: post.labelIds }}, {$addToSet: {postIds:req.body.id}}, {multi: true}).exec()
emil.c
  • 1,987
  • 2
  • 26
  • 46