【问题标题】:Mongoose doesn't save data while reporting them being savedMongoose 在报告数据被保存时不保存数据
【发布时间】:2015-04-15 02:30:26
【问题描述】:

我在使用 mongoose 将一些数据保存到 Mongo 时遇到问题。

在我正在做的数据库模块中:

  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
      }
    });
  };

newMove 在 GameSchema 中被定义为虚方法

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] = "";
  }
});

transformState 作为静态方法

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
      });
  };
};

如何调用 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));
  });
});

根据要求,我的 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"]
  }
})

另外,这是我第二次请求游戏状态的方式:

//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));
};

如您所见,每次我从客户端获得新动作时,我都会修改当前游戏字段并保存该游戏。当我用game.save(Game.transformState(callback)); 保存它时,它是“保存的”,这意味着回调中的数据是正确的。但是如果我再次尝试请求游戏状态,我可以看到它没有保存。我也尝试手动检查 MongoDB,确实没有保存。我要解释的是,game.save(Game.transformState(callback)); 函数 callback 以更新的游戏状态执行,我可以在客户端看到它,但状态实际上并没有保存在数据库中。

【问题讨论】:

  • 我可能有误会,但是您是否希望您的newMove virtual 被保存?因为虚拟不会被持久化,并且与this 相比,您的方法中缺少一些this.set 调用。 callback 是什么?你怎么打电话给addMove(...)
  • @Tony 是的,我希望按照guide 中的说明进行操作(搜索 mad.name.full = 'Breaking Bad';),但它似乎不起作用。我刚刚尝试了您的建议,并将game.newMove = move; 换成game.set('newMove', move); 并且行为仍然相同。然后我尝试将 virtual 放在一起并使用 game._field[to] = game._field[from]; game._field[from] = ""; 但更改仍未保存。
  • @Tony Callback 是我从套接字控制器方法传递给数据库方法的函数,它需要两个参数:(错误,数据)。我修改了 OP 并在我调用数据库方法的地方添加了代码。
  • 如果您发现那里有任何问题,我已经添加了 Schema 和一些奖励代码。我会尝试你的建议。 compose.io 是否可能有问题,因为我没有使用本地 mongoDB?我猜不是因为我可以更新其他文档,而是为了让你知道......
  • 我想通了,检查我的答案。 :)

标签: node.js mongodb mongoose


【解决方案1】:

显然,如果您直接修改数组,mongoose 不会检测到字段已更改。为了触发检测,我使用了this.markModified('_field');

我后来发现还有其他一些方法可以做到这一点: Mongoose: assign field of type 'array of Strings'

【讨论】:

  • 当我看到你的架构时我就知道了。
猜你喜欢
  • 1970-01-01
  • 2020-09-13
  • 2017-01-16
  • 2017-07-27
  • 1970-01-01
  • 2018-01-14
  • 1970-01-01
  • 2015-11-13
  • 1970-01-01
相关资源
最近更新 更多