3

我有一个包含 1 亿个文档的集合。我想安全地更新一些文档(安全地我的意思是仅在文档尚未更新时才更新它)。有没有一种有效的方法可以在 Mongo 中做到这一点?

我计划将 $isolated 运算符与限制子句一起使用,但似乎 mongo 不支持限制更新。

这看起来很简单,但我被困住了。任何帮助,将不胜感激。

4

1 回答 1

1

根据 Sammaye,看起来没有“正确”的方法来做到这一点。我的解决方法是按照 mongo 网站上的概述创建一个序列,然后简单地在我的集合中的每条记录中添加一个“seq”字段。现在我有一个独特的字段,可以可靠地对其进行排序以进行更新。

可靠的可排序在这里很重要。我打算只对自动生成的 _id 进行排序,但我很快意识到自然顺序与 ObjectId 的升序不同(从这个页面看来,字符串值优先于与我观察到的行为匹配的对象值在测试中)。此外,完全有可能将记录重新定位到磁盘上,这使得自然顺序对排序不可靠。

所以现在我可以查询具有最小“seq”的记录,该记录尚未更新以获得包容性起点。接下来我查询'seq'大于我的起点的记录并跳过(重要的是跳过,因为如果你删除文档等,'seq'可能是稀疏的......)我想要更新的记录数。将该查询限制为 1,您将获得一个非包含端点。现在我可以使用“updated”= 0、“seq”>= 我的起点和 < 我的终点的查询发出更新。假设没有其他线程击败我,更新应该给我我想要的。

下面是步骤:

  1. 使用 findAndModify 创建一个自增序列
  2. 向您的集合添加一个使用自动递增序列的字段
  3. 查询以找到合适的起点: db.xx.find({ updated: 0 }).sort({ seq: 1 }).limit(1)
  4. 查询以找到合适的端点: db.xx.find({ seq: { $gt: startSeq }}).sort({ seq: 1 }).skip(updateCount).limit(1)
  5. 使用起点和终点更新集合: db.xx.update({ updated: 0, seq: { $gte: startSeq }, seq: { $lt: endSeq }, $isolated: 1}, { updated: 1 } ,{ 多:真 })

相当痛苦,但它可以完成工作。

于 2013-04-26T18:52:04.777 回答