如何在MongoDB中正确执行批量插入/更新操作

19

我正在尝试:

  • 根据搜索条件查找文档,
  • 如果找到,则更新一些属性;
  • 如果没有找到,则插入一个带有某些属性的文档。

我正在使用 Bulk.unOrderedOperation,因为我还要执行单个插入操作。并且我想在一次操作中针对数据库完成所有操作。

然而,某些情况导致更新/插入操作未能插入任何内容。

这是插入文档:

  var lineUpPointsRoundRecord = {
    lineupId: lineup.id,  // String
    totalPoints: roundPoints, // Number
    teamId: lineup.team, // String
    teamName: home.team.name, // String
    userId: home.iduser, // String
    userName: home.user.name, // String
    round: lineup.matchDate.round, // Number
    date: new Date()
  }

这是要更新或插入的文档:

  var lineUpPointsGeneralRecord = {
    teamId: lineup.team, // String
    teamName: home.team.name, // String
    userId: home.iduser, // String 
    userName: home.user.name, // String
    round: 0,
    signupPoints: home.signupPoints, // String
    lfPoints: roundPoints+home.signupPoints, // Number 
    roundPoints: [roundPoints] // Number
  };

这是我尝试进行upsert/update的方法:

var batch = collection.initializeUnorderedBulkOp();

batch.insert(lineUpPointsRoundRecord);

batch.find({team: lineUpPointsRoundRecord.teamId, round: 0}).
  upsert().
  update({
    $setOnInsert: lineUpPointsGeneralRecord,
    $inc: {lfPoints: roundPoints},
    $push: {roundPoints: roundPoints}
  });

batch.execute(function (err, result) {
  return cb(err,result);
});

为什么不会进行upsert/更新操作呢?

注意

这是使用waterline ORM编写的JS代码,它还使用mongodb本地驱动程序。

3个回答

19

你的语法基本上是正确的,但是你的执行过程有误,应该将"upsert"操作与其他修改操作"分离"。否则在进行"upsert"时这些操作会"冲突"并产生错误:

LineupPointsRecord.native(function (err,collection) {

    var bulk = collection.initializeOrderedBulkOp();

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

确保你的 sails-mongo 是最新版本,支持正确包含了最近的本地node驱动程序,以便进行批量操作。最新版本支持v2驱动程序,这对此很好。


10

我建议使用bulkWrite样例代码与bulk upsert来操作许多文档:

在这种情况下,您将创建具有唯一md5的文档。如果文档已存在,则会更新该文档,但不像经典insertMany那样创建新文档。

const collection = context.services.get("mongodb-atlas").db("master").collection("fb_posts");

return collection.bulkWrite(
  posts.map(p => { 
    return { updateOne:
      {
        filter: { md5: p.md5 },
        update: {$set: p},
        upsert : true
      }
    }
  }
  ),
  { ordered : false }
);

https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/


-1
通常我总是将upsert设置为更新的属性。此外,更新应该能够自行找到记录,因此无需单独查找。
根据环境,$可能需要也可能不需要。
batch.update(
 {team: lineUpPointsRoundRecord.teamId, round: 0},
    {      
      $setOnInsert: lineUpPointsGeneralRecord,
      $inc: {lfPoints: roundPoints},
      $push: {roundPoints: roundPoints},
      $upsert: true
    });

3
"$upsert" 不是一个有效的选项。问题还提到了“批量”操作,OP 使用的语法是正确的。这是不正确的。 - Blakes Seven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接