如何使用upsert行为正确更新文档? (Mongo bug SERVER-10711)

时间:2015-08-15 01:28:40

标签: node.js mongodb sails.js mongodb-query waterline

我尝试更新具有更新的文档(如果找到),否则插入

这是我尝试的东西(使用sails waterline ORM使用monodb节点驱动程序):

var roundPoints = 93;
var lfPoints = 10 + roundPoints;
var lineUpPointsGeneralRecord = {
  round: 0,
  teamId: "real-madrid-9248",
  totalPoints: roundPoints,
  teamName: "minuto93",
  userId: "bbc1902",
  userName: "Risas Pizza",
  signupPoints: 10,
  lfPoints: lfPoints
};

LineupPointsRecord.native(function (err,collection) {
collection.update(
  {teamId: lineUpPointsGeneralRecord.teamId, round: 0},
  {
    $setOnInsert: lineUpPointsGeneralRecord,
    $inc: {lfPoints: roundPoints},
    $push: {roundPoints: roundPoints}
  },
  {upsert: true},
  function (err,updateResult) {
    sails.log.debug(err,updateResult);
  });
});

但是抱怨失败了:

code: 16836,
err: 'Cannot update \'lfPoints\' and \'lfPoints\' at the same time' } null

我做错了什么?

修改

This seems to be a known issue.但我真的不想最终实现实施变通办法。我该如何应对呢?

1 个答案:

答案 0 :(得分:2)

发生错误是因为当$setOnInsert$inc同时发生“upsert”时,$push操作都试图在文档中设置项目。由于错误报告,您无法在单次更新中修改具有两个不同运算符的文档的相同属性。

然后解决方案是“分离”更新,以便只有一个操作“仅”执行$setOnInsert而另一个操作将执行文档匹配的其他更改。最佳方法是使用Bulk Operations,以便所有请求立即发送到服务器:

LineupPointsRecord.native(function (err,collection) {

    var bulk = collection.initializeOrderedBulOp();

    // Match and update only. Do not attempt upsert
    bulk.find({
        "teamId": lineUpPointsGeneralRecord.teamId,
        "round": 0
    }).updateOne({
        "$inc": { "lfPoints": roundPoints },
        "$push": { "roundPoints": roundPoints }
    });

    // Attempt upsert with $setOnInsert only
    bulk.find({
        "teamId": lineUpPointsGeneralRecord.teamId,
        "round": 0
    }).upsert().updateOne({
        "$setOnInsert": lineUpPointsGeneralRecord
    });

    bulk.execute(function (err,updateResult) {
        sails.log.debug(err,updateResult);
    });
});

由于第二次操作只会尝试文件不匹配的upsert,因此没有冲突,因为没有其他操作。在第一个操作中,这将“仅”在文档“匹配”的位置进行更改,并且由于此处没有尝试的upsert,因此也没有冲突。

确保您的sails-mongo是支持批量操作的最新版本,包括最近的节点本机驱动程序。最近支持v2驱动程序,这对此很好。