我的应用程序跟踪整个系统中数据的移动。记录 Action 后,会将其放置在一个单独的集合中,该集合确定文档是否在途中,可用或不再使用。我使用$ addToSet放置_id,并使用$ pullAll来确保将文档从途中移到可用时不会重复。但是,当_id完全移动到新位置时,我需要从旧位置中删除旧数据并将其插入新位置。插入工作正常,但我不知道如何从旧位置正确删除数据。这些都在 meteor call 和Mongodb中

          if last.status is "Enroute"
            LastLocation.update locationId: last.locationId,partId: last.partId,
                $addToSet:
                    enroutePurchaseIds: lastPurchaseId
                $pullAll:
                    availiblePurchaseIds: lastPurchaseId
                    outOfServicePurchaseIds: lastPurchaseId

最佳答案

更新

您可以从即将发布的4.4版本中运行merge命令,该命令允许更新运行聚合的同一集合。将数组作为旧位置和新位置传递

db.collection.aggregate([
  {"$match":{"location":{"$in":[oldLocation,newLocation]}}},
  {"$addFields":{"sortOrder":{"$indexOfArray":[[oldLocation,newLocation],"$location"]}}},
  {"$sort":{"sortOrder":1}},
  {"$group":{
    "_id":null,
    "oldLocationDoc":{"$first":"$$ROOT"},
    "newLocationDoc":{"$last":"$$ROOT"}
  }},
  {"$addFields":{
    "oldLocationDoc.old":{
      "$filter":{
        "input":"$oldLocationDoc.old",
        "cond":{"$ne":["$$this",oldLocation]}
      }
    },
    "newLocationDoc.new":{"$concatArrays":["$newLocationDoc.new",[newLocation]]}
  }},
  {"$project":{"locations":["$oldLocationDoc","$newLocationDoc"]}},
  {"$unwind":"$locations"},
  {"$replaceRoot":{"newRoot":"$locations"}},
  {"$merge":{
    "into":{"db":"db","coll":"collection"},
    "on":"_id",
    "whenMatched":"merge",
    "whenNotMatched":"failed"
  }}
]

原始

不能在单个更新操作中将数组/字段值从一个文档移动到另一文档。

您可能想使用 transactions 以原子方式执行多文档更新。需要副本集。
var session = db.getMongo().startSession();
var collection = session.getDatabase('test').getCollection('collection');
session.startTransaction({readConcern: {level:'snapshot'},writeConcern: {w:'majority'}});
collection.update({location:oldLocation},{$pull:{availiblePurchaseIds:lastPurchaseId}});
collection.update({location:newLocation},{$push:{enroutePurchaseIds:lastPurchaseId}});
session.commitTransaction()
session.endSession()

其他选项是在独立mongod实例的情况下执行 bulk 更新。
var bulk = db.getCollection('collection').initializeUnorderedBulkOp();
bulk.find({location:oldLocation}).updateOne({$pull:{availiblePurchaseIds:lastPurchaseId}});
bulk.find({location:newLocation}).updateOne({$push:{enroutePurchaseIds:lastPurchaseId}});
bulk.execute();

07-24 18:10
查看更多