Question

I'm losing some (but not all) changes to my Mongoose model when populating after a save. I splice a random (here simplified to just the first) element out of an array and assign it into another variable. Both the target (activeTile) and the array (unusedTiles) are updated in the database but in the populate call I'm only seeing updates to the target and not the array.

// Executing code
console.log('==0> ' + gamestate.unusedTiles.length);
console.log('==0> ' + gamestate.activeTile.tile);
gamestate.nextTile(function(err, gamestate2) {
    console.log('==2>' + gamestate2.unusedTiles.length);
    console.log('==2>' + gamestate2.activeTile);
    gamestate2.populate('activeTile unusedTiles', function(err, gamestate3) {
        console.log('==3> ' + gamestate3.unusedTiles.length);
        console.log('==3> ' + gamestate3.activeTile);
    });
});

// And in the Mongoose model
var gamestateSchema = mongoose.Schema({
    unusedTiles: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Tile' }],
    activeTile: { type: mongoose.Schema.Types.ObjectId, ref: 'Tile' }
});

gamestateSchema.methods.nextTile = function(callback) { 
    var gamestate = this;
    gamestate.activeTile = gamestate.unusedTiles.splice(0, 1)[0];           
    gamestate.markModified('unusedTiles');
    gamestate.save(function(err, gamestate1) {
        console.log('==1> ' + gamestate1.unusedTiles.length);
        console.log('==1> ' + gamestate1.activeTile);
        callback(err, gamestate1);
    });        
}

And the resulting console output appears like this:

==0> 65
==0> 5356b8907b915c0000e068a2
==1> 64
==1> 5356b8907b915c0000e06887
==2> 64
==2> 5356b8907b915c0000e06887
==3> 65
==3> {
       _id: 5356b8907b915c0000e06887,
       ... // rest of tile object
     }

I would expect both changes to be seen in the populate callback. So the new length of the unusedTiles array should be 65 not 64. Any idea what is going on?

I'm using Mongoose 3.8.1.

Was it helpful?

Solution

It looks like I needed to mark the array as modified again immediately before the populate. I guess Mongoose fetches the old array out of the database for the populate otherwise? That doesn't make much sense since the populate is done in the save callback. Not sure but it is working with that change.

gamestate2.markModified('unusedTiles');
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top