7
votes

I am trying to pull/remove values from an array (subdocument).

Example doc:

{
   _id: 5150a1199fac0e6910000002,
   name: 'some name,
   items: [{
      id: 23,
      name: 'item name 23'
   },{
      id: 24,
      name: 'item name 24'
   }]
}

I have the doc in memory as I pulled it from mongo already. I am trying:

var left = object.items.pull({id: 24});
console.log(left)

Outputs:

[{
   id: 23,
   name: 'item name 23',
   _id: 5150a1199fac0e6910000045
},{
  id: 24,
  name: 'item name 24',
  _id: 5150a1199fac0e6910000002 
}]

So looks like I already have a problem. The array returned from the pull call should be whats left in the array after the pull . Not sure why it did not pull from the item array. Does this only support pulling by ObjectId ant not user defined fields?

I call save:

object.save();

Mongoose logs this as the query:

Mongoose: mycollection.update({ _id: ObjectId("5150901ac345824a07000002"), __v: 3 }) 
  { '$inc': { __v: 1 }, '$pull': 
    { attachments: { _id: { '$in': [ ObjectId("5150c64d63773efb1f000002") ] } } } } {}

This shows why my document is not being removed. The _id of the array item that should be removed is:

_id: 5150a1199fac0e6910000002

The item that mongoose is sending to the database to remove is:

ObjectId("5150c64d63773efb1f000002")

Any ideas what I am doing wrong? I am trying to delete by something other than _id, not sure if that is possible but from the docs looks to be.

1

1 Answers

16
votes

I discovered that the $pull command doesn't work for me either unless I include the callback in the arguments list.

In my situation, this format did not work:

UserAlerts.findOneAndUpdate({userId: userId}, {$pull: {alerts: {_id: alertId}}});

But this format did:

UserAlerts.findOneAndUpdate({userId: userId}, {$pull: {alerts: {_id: alertId}}}, function(err, data){
  console.log(err, data);
});

According to the documentation, it seems like both should work, but don't. The reason is because the first way requires you to call .exec() on the returned object, whereas the callback version calls exec() automatically. Caused some confusion for me also.

So you need to do something like this:

UserAlerts.findOneAndUpdate({userId: userId}, {$pull: {alerts: {_id: alertId}}}).exec();