Mongoose: Removing multiple sub documents correct way

Created on 21 Jan 2013  路  9Comments  路  Source: Automattic/mongoose

First I tried the first way:


item.tasks.forEach(function(task){
            if (task.finished)
                tasks.remove(task)
})

item.save() 

but after that I have NOT ALL finished task where deleted.

Then I did with async saving item after each sub doc remove:


        var tasksToRemove= [];
        tasks.forEach(function(task){
            if (task.finished)
                tasksToRemove.push(task)
        })

        async.mapSeries(tasksToRemove, function(task, callback){
            console.log('Removing finished tasks: remove task', task._id )
            tasks.remove(task)
            item.save(function(err){
                callback(err)
            })
        }, function(err){

        })

All tasks where deleted from DB.

What is the issue with first way of removing sub docs?

Most helpful comment

sure.

var i = item.tasks.length;
while (i--) {
  var task = item.tasks[i];
  if (blah) {
    item.tasks.remove(task); // or just task.remove()
  }
}

All 9 comments

I've managed to to this with pull method (provided there list of task that should be deleted). Is it correct way of deleting? If yes, lets close the ticket.

Removing elements from the array during forward iteration causes elements to be skipped over. This is true when using forEach or even a for loop. Instead, iterate the array in reverse manually and it will work the way you expect.

"iterate the array in reverse manually" didn't get it, could you explain?

sure.

var i = item.tasks.length;
while (i--) {
  var task = item.tasks[i];
  if (blah) {
    item.tasks.remove(task); // or just task.remove()
  }
}

Ok, thank you, I got what you mean. Is it possible to use:
task.reverse().forEach( ?

no b/c you'll still be iterating forward while removing elements. test it out and see what i mean.

Oh, I got it now, thanks =)

:)

Thank you!

Was this page helpful?
0 / 5 - 0 ratings