2013-04-26 95 views
2

我有一个包含1亿个文档的集合。我想安全地更新许多文档(安全地说,我的意思是只有在文档尚未更新时才更新文档)。在Mongo中有没有一种有效的方法?Mongodb更新数量有限的文档

我打算使用具有限制子句的$ isolated操作符,但似乎mongo不支持限制更新。

这似乎很简单,但我卡住了。任何帮助,将不胜感激。

+1

嗯,我再也不能向你提出一个JIRA链接了,我很害怕:https://jira.mongodb.org/browse/SERVER-1599 – Sammaye 2013-04-26 13:17:51

+0

谢谢。我注册的只是为了这个问题投票:-)现在找到一些令人费解的解决方法,直到功能实施... – jckdnk111 2013-04-26 13:25:48

+0

“安全” - 我不清楚为什么限制与此有关 - 如果您计划更新所有文档,并使用“{multi:true}”,那么每个文档将只更新一次。你能解释一下你的确切用例吗?我怀疑可能会有解决办法。 – 2013-04-26 15:04:18

回答

1

Per Sammaye,它看起来不像有一个“适当”的方式来做到这一点。 我的解决方法是创建一个sequence as outlined on the mongo site,并简单地为我的集合中的每条记录添加一个“seq”字段。现在我有一个独特的领域,这是可靠排序更新。

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

因此,现在我可以查询具有最小'seq'的记录,该记录尚未更新以获得包含的起点。接下来,我查询'seq'大于我的起始点并跳过的记录(跳过这一点非常重要,因为'seq'可能会稀疏,如果您删除文档等...)我想要更新的记录数。对该查询设置1的限制,并且您有一个非包含端点。现在我可以使用'updated'= 0,'seq'> =我的出发点和<我的端点进行更新。假设没有其他线程殴打我的冲击更新应该给我我想要的。

这里又是具体步骤:

  1. 使用findAndModify
  2. 创建一个自动递增序列的字段添加到您的收藏它使用自动递增序列
  3. 查询找到一个合适的切入点:db.xx.find({更新: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})

很痛苦,但它完成了工作。