使用猫鼬 findOneandUpdate 时无法读取未定义的属性“_id”

bri*_*dip 2 mongoose node.js mean.io

我正在使用 mean.io 制作体育赛事管理系统。我正在尝试使用 rest api 更新模型 Player,它从 mongoose 抛出此错误:

  { _id: 5411c79895d600440c698fa1,
  email: 'abc@bcd.com',
  name: 'James Bond',
  username: 'james.bond',
  games: [ 5411bd54786cfe2420f1e27a ],
  teams: [],
  roles: [ 'authenticated' ] }

[TypeError: Cannot read property '_id' of undefined]

PUT /api/players/5411c79895d600440c698fa1 500 199.402 ms - 36
Run Code Online (Sandbox Code Playgroud)

我还尝试从播放器中删除 _id 属性,但它也不起作用。我用来更新模型播放器的方法是:

exports.update = function(req, res) {
    var player = req.player;
    player = _.extend(player, req.body);        
    console.log(player);

    Player.findOneAndUpdate(req.params.playerId, player,{new:true}, function (err, updatedPlayer) {
        console.log(err);
        if (err) {
            return res.status(500).json({
                error: 'Cannot update the player'
            });
        }
        res.json(updatedPlayer);
    });
Run Code Online (Sandbox Code Playgroud)

而且如果我使用model.save默认包article中提供的方法mean.io,它会显示另一个错误。我user在播放器包app.js文件中扩展了模型。因此,每当我尝试更新一个字段时,我在其中声明的字段app.js都是必需的,并且会抛出来自 mongoose 的 path required 错误。

Mat*_*yhr 5

您的更新请求中有两个问题。

首先,它findOneAndUpdate需要一个 dict 作为查询,而不仅仅是 id,所以你应该提供它{_id: req.params.playerId}

其次,将 mongoose 对象作为更新数据传递是有风险的,您应该将其转换为这样的字典var _player = player.toObject(),然后_player传递给更新请求。请记住,您需要删除_idparam ,_player因为您无法更改_id文档的 。在做更新之前delete _player._id,你应该没问题。此外,默认new设置为true,因此您不需要选项字典。

这是您的工作代码:

var player = _.extend(req.player, req.body);        
var _player = player.toObject();
delete _player._id;

var query = {_id: req.params.playerId};
Player.findOneAndUpdate(query, _player, function (err, updatedPlayer) {
    ...
});
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,您甚至不必进行第一个操作。由于您只想更新req.body您可以执行的数据:

var query = {_id: req.params.playerId};
var data = {
    $set: req.body,
};
Player.findOneAndUpdate(query, data, function (err, updatedPlayer) {
    ...
});
Run Code Online (Sandbox Code Playgroud)

这将更新query与 中的值匹配的玩家的所有字段req.body