2

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.

8
  • can you try console.logging item.save(function (err, itemSaved) { the itemSaved ? Commented Jul 7, 2014 at 20:44
  • I updated my question in this way : saved item looks ok, but not after the last Find query.. Commented Jul 7, 2014 at 20:56
  • How is slots defined in your schema? Commented Jul 7, 2014 at 20:59
  • I updated my question, so you can now see my Schema Commented Jul 7, 2014 at 21:03
  • 1
    I ran into this a while ago, actually. item.save sometimes does not call update on changed values properly, if you actually step through using a debugger, you will see interesting stuffs. Commented Jul 7, 2014 at 21:34

2 Answers 2

4

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) {
        ...
Sign up to request clarification or add additional context in comments.

2 Comments

Good solution, you can also just do item.markModified('slots') right?
@tpae That also works, but it's not as efficient as Mongoose then has to update the whole array instead of just the modified element.
2

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) {

1 Comment

Sry, but it's not exactly what I search. I need to set one element of the 'slots' array to null, not to reset it to its blank state (not sure if I explain well ^^)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.