简体   繁体   English

如何在 MongoDB 的一次往返中根据查询更新多个文档?

[英]How to do update multiple docs based on a query in one round trip in MongoDB?

Imagine you have a collection with documents as follows:假设您有一个文档集合,如下所示:

{
    "_id": "SOME_MONGO_ID",
    "rank": 1
}

And given an _id want to update increment all the documents with rank higher than it.给定一个 _id 想要更新所有排名高于它的文档。

If I know the rank I can use UpdateMany to increment the ranks higher than it using a filter.如果我知道排名,我可以使用 UpdateMany 来增加比使用过滤器更高的排名。 However that would require two round trips one to get the rank and another to do the update many.然而,这将需要两次往返,一次获得排名,另一次进行多次更新。

Is it possible to use a pipeline to lookup the rank and then do the update in one round trip?是否可以使用管道查找排名,然后在一次往返中进行更新?

I'm using the c# mongodb driver.我正在使用 c# mongodb 驱动程序。

This needs to work inside a transaction so we can't use '$merge'这需要在事务内部工作,所以我们不能使用“$merge”

You can use $lookup with $merge .您可以将$lookup$merge一起使用。 If you expect few and small documents to return, you can use '$match' first, but it has the disadvantage of temporarily putting all of these updated docs in one document:如果你希望返回的文档很少而且很小,你可以先使用'$match',但它的缺点是暂时将所有这些更新的文档放在一个文档中:

db.collection.aggregate([
  {$match: {_id: "SOME_MONGO_ID"}},
  {$lookup: {
      from: "collection",
      as: "updated",
      let: {thRank: "$rank"},
      pipeline: [{$match: {$expr: {$gt: ["$rank", "$$thRank"]}}}]
    }
  },
  {$unwind: "$updated"},
  {$replaceRoot: {newRoot: "$updated"}},
  {$project: {rank: {$add: ["$rank", incVal]}}},
  {$merge: {into: "collection"}}
])

See how it works on the playground exampleplayground 示例中查看它是如何工作的

If you expect many documents (or large ones) to return, you can use $lookup first:如果您希望返回很多文档(或大文档),您可以先使用$lookup

db.collection.aggregate([
  {$lookup: {
      from: "collection",
      as: "ref_id",
      let: {doc_id: ObjectId("62fb40acd762c3e1150e0134")},
      pipeline: [{$match: {$expr: {$eq: ["$_id", "$$doc_id"]}}}]
    }
  },
  {$match: {$expr: {$gt: ["$rank", {$first: "$ref_id.rank"}]}}},
  {$unset: "ref_id"},
  {$project: {rank: {$add: ["$rank", incVal]}}},
  {$merge: {into: "collection"}}
])

See how it works on the playground example - many docs看看它是如何在playground 示例上工作的——许多文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM