MongoDB更新有限数量的文档

3

我有一个包含1亿条文档的集合。我想安全地更新其中一些文档(安全更新指仅在尚未更新的情况下更新文档)。是否有一种有效的方法在Mongo中实现这个目标?

我原本打算使用$isolated运算符和limit子句,但是似乎Mongo不支持限制更新。

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


1
抱歉,我恐怕无法为您提供更多的咨询,只能给您一个JIRA链接:https://jira.mongodb.org/browse/SERVER-1599 - Sammaye
谢谢。我注册只是为了投票支持这个问题 :-) 现在要找到一些复杂的解决方法,直到这个功能被实现... - jckdnk111
“safely” - 我不清楚为什么限制与此有关 - 如果您计划更新所有文档并使用“{multi:true}”,则每个文档将仅更新一次。您能解释一下您的确切用例吗?我怀疑可能有一个解决方法。 - Asya Kamsky
我不会更新所有文档 -- 它将是一个未知数量的文档(例如,可能是前100个文档或者可能是前1000个)。 - jckdnk111
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 },{ multi: true })

有些麻烦,但它能完成任务。


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