【问题标题】:How to properly do a Bulk upsert/update in MongoDB如何在 MongoDB 中正确地进行批量更新插入/更新
【发布时间】:2015-11-08 06:04:30
【问题描述】:

我正在尝试:

  • 根据搜索条件查找文档,
  • 如果找到,更新一些属性
  • 如果不插入具有某些属性的文档。

我正在使用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()
  }

这是 upsert 文档:

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

这就是我尝试更新/更新的方式:

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

为什么不更新插入/更新?

注意

那是使用水线 ORM 的 JS 代码,它也使用了 mongodb 原生驱动。

【问题讨论】:

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


    【解决方案1】:

    通常我总是将 upsert 设置为更新时的属性。此外,更新应该能够找到记录本身,因此无需单独查找。

    根据环境,$ 可能需要也可能不需要。

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

    【讨论】:

    • $upsert 不是有效选项。该问题还提到了“批量”操作,并且 OP 使用的语法是正确的。这是不正确的。
    【解决方案2】:

    您的语法基本上是正确的,但您的一般执行是错误的,您应该将“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 是正确支持批量操作的最新版本,包括最新的节点本机驱动程序。最新的支持 v2 驱动,这很好。

    【讨论】:

      【解决方案3】:

      我建议在许多文档中使用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/

      【讨论】:

        猜你喜欢
        • 2017-07-12
        • 1970-01-01
        • 2011-02-24
        • 2014-10-06
        • 1970-01-01
        • 2011-05-25
        • 1970-01-01
        • 2022-12-21
        • 1970-01-01
        相关资源
        最近更新 更多