Reputation: 722
I'm having a problem saving some data to Mongo using mongoose.
In my database module I'm doing:
self.addMove = function (gameId, move, callback) {
Game.findById(gameId, function (err, game) {
if (err)
callback(err);
else {
game.newMove = move; //apply new move
game.save(Game.transformState(callback)); //save the game
}
});
};
where newMove is defined as virtual method in GameSchema as
GameSchema.virtual('newMove').set(function (move) {
if (move.player !== move.piece[0])
return;
if (allowedMove(move)) { //if piece is allowed to move
var from = positionToIndex(move.from),
to = positionToIndex(move.to);
this._field[to] = this._field[from]; //move it
this._field[from] = "";
}
});
and transformState as static method
GameSchema.statics.transformState = function (callback) {
return function (err, data) {
if (err)
callback(err);
else
callback(null, {
_id: data._id,
moves: data.moves,
field: data.field //data.field transforms 1D array into 2D client-useable array
});
};
};
How I call addMove:
socket.on('addMove', function (msg) {
console.log('New move: ' + msg);
var msg = JSON.parse(msg);
db.addMove(msg._id, msg.move, function (err, data) {
if(!err)
io.emit('getState', JSON.stringify(data));
});
});
As requested, my GameSchema:
GameSchema = new Schema({
moves: [MoveSchema],
_field: {
type: [String],
default: ["WR", "WN", "WB", "WQ", "WK", "WB", "WN", "WR", "WP", "WP", "WP", "WP", "WP", "WP", "WP", "WP", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "BP", "BP", "BP", "BP", "BP", "BP", "BP", "BP", "BR", "BN", "BB", "BQ", "BK", "BB", "BN", "BR"]
}
})
And as a bonus, this is how I request game state second time:
//sockets.js
socket.on('getState', function (msg) {
console.log('User requested game state!');
var msg = JSON.parse(msg);
db.getGame(msg._id, function (err, data) {
if(!err)
io.emit('getState', JSON.stringify(data));
});
});
//database.js
self.getGame = function (id, callback) {
Game.findById(id, Game.transformState(callback));
};
As you can see, each time I get new move from client I modify current game field and save that game. When I save it with game.save(Game.transformState(callback));
it is "saved" which means data in callback are correct. But if I try to request game state again, I can see it's not saved. I also tried checking MongoDB manually and indeed is not saved. What I'm trying to explain is that in line game.save(Game.transformState(callback));
function callback
is executed with updated game state and I can see it on client but the state is actually not saved in database.
Upvotes: 0
Views: 519
Reputation: 722
Apparently, mongoose doesn't detect field was changed if you modify arrays directly. To trigger detection I used this.markModified('_field');
There are some other methods to do this I found out later: Mongoose: assign field of type 'array of Strings'
Upvotes: 2