我有一些代码检查Mongo集合中的每个对象(迭代没有参数的find()的结果),并对其中一些进行更改。看起来这不安全:我的更改被保存,但是当我继续迭代光标时,更改对象的子集(10-15%)会再次出现。我没有更改文档ID或任何有索引的内容。
我想通过提前获取所有文档ID(将光标转换为数组)来避免这个问题,但这些是大型集合,所以我真的想避免这种情况。
我注意到默认情况下find()的结果似乎没有任何已定义的顺序,所以我尝试对游标进行显式排序,{“_ id”:1}。这似乎解决了这个问题 - 无论我修改什么,现在都没有出现过两次。但我不知道这是不是一个好的/可靠的方法。据我从文档中可以看出,添加排序不使其预先查询所有ID;如果是这样,那很好,但后来我不知道为什么会解决这个问题。
在更改内容时使用游标是不是一个坏主意?
如果重要的话,我正在使用Scala / Casbah。
答案 0 :(得分:8)
听起来你想要的是快照查询。以下是有关如何执行此操作的更多信息:
http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database
答案 1 :(得分:0)
考虑使用修改多个文档的update
命令:
http://docs.mongodb.org/manual/tutorial/modify-documents/
此外,由于您只修改了某些对象,因此请考虑使用仅返回您实际要修改的文档的查询,而不是扫描整个集合。
迭代find
的结果并修改对象可能看起来更方便和灵活,因为您不仅限于使用更新运算符可以执行的操作,而且您可以使用您选择的语言编写代码来修改该文件。但是,您描述的问题以及其他限制:
http://docs.mongodb.org/manual/faq/developers/#faq-developers-isolate-cursors
例如,快照查询不是100%安全的,并且它们不能与分片集合一起使用,因此如果您以后决定进行分片,那么您的解决方案将会中断。
如果您需要以更复杂的方式修改大量对象,可以使用map-reduce或聚合管道来解决您的问题: