meriadec
meriadec

Reputation: 2983

Set array element to null with Mongoose

I'm encountering an interesting problem, trying to set to null an element of a sub-array in mongo with mongoose (wich seems ridiculously obvious, yep).

My Schema looks like :

var ItemSchema = new Schema({
  name : String,
  slots: { type: [{ type : Schema.Types.ObjectId, ref: 'Slot' }], default: [] }
});

My data looks like :

{
  _id  : ObjectId("53bafbfd00cbcc3a1178e11b"),
  name : "item 1",
  slots: [null, null, ObjectId("53baf297d63228631029d2f8"), null, null]
},
{
  _id  : ObjectId("53baf297d63228631029d2f8"),
  name : "item 2",
  slots: [ObjectId("53baf1b3fecfe25c10233801"), null, null, null, null]
}

nb: the nullvalues are important for order logical purposes.

So, let's imagine I get the first of these items :

Items.findById('53bafbfd00cbcc3a1178e11b', function (err, item) {

  console.log(item.slots);
  // [null, null, "53baf297d63228631029d2f8", null, null] --> OK

  // BIG update here
  item.slots[2] = null;

  item.save(function (err, itemSaved) {

    // no errors

    console.log(itemSaved.slots);
    // [null, null, null, null, null] --> Well, so everything works, right ?

    // so let's find the same item again !

    Items.findById('53bafbfd00cbcc3a1178e11b', function (err, itemSearched) {

      console.log(itemSearched.slots);
      // [null, null, "53baf297d63228631029d2f8", null, null] --> what ?? id still here ?

    });

  });

});

So the id isn't set to null even if save worked.. I don't get it, really. I need so much an explanation ! Thanks in advance.

Upvotes: 2

Views: 1933

Answers (2)

JohnnyHK
JohnnyHK

Reputation: 311865

It seems you need to explicitly mark that element as modified or save won't pick up the change:

item.slots[2] = null;
item.markModified('slots.2');
item.save(function (err, itemSaved) {
    ....

Perhaps because null is not a valid ObjectId.

The other way to do this is with update and $unset:

Items.update(
    {_id: '53bafbfd00cbcc3a1178e11b'},
    {$unset: {'slots.2': 1}}, function(err, numAffected) {
        ...

Upvotes: 4

tpae
tpae

Reputation: 6346

Try this instead:

Items.update(
    {_id: '53bafbfd00cbcc3a1178e11b'}, 
    {$set: { slots: [null, null, null, null, null] } }, 
function(err, results) {
  Items.findById('53bafbfd00cbcc3a1178e11b', function (err, itemSearched) {
      console.log(itemSearched.slots);
    });
  });
});

Make a wrapper function around it, like this:

ItemSchema.statics.clearSlot = function(id, slot, cb) {
  var self = this;
  this.findById(id, function(err, item) {
    var slots = item.slots;
    slots[slot] = null;
    self.update({_id: id}, {$set: {slots: slots}}, cb);
  });
});

Something like that. lol

Call it like

Item.clearSlot(id, 2, function(err, updated) {

Upvotes: 2

Related Questions