8

我有一些代码检查 Mongo 集合中的每个对象(迭代没有参数的 find() 的结果),并对其中的一些进行更改。这样做似乎不安全:我的更改已保存,但是当我继续遍历光标时,更改对象的子集(10-15%)第二次出现。我没有更改文档 ID 或任何有索引的东西。

我想我可以通过提前获取所有文档 ID(将光标转换为数组)来避免这个问题,但这些都是大型集合,所以我真的很想避免这种情况。

我注意到默认情况下 find() 的结果似乎没有任何定义的顺序,所以我尝试在光标 {"_id":1} 上进行显式排序。这似乎已经解决了这个问题——无论我修改什么,现在都没有出现两次。但我不知道这是否是一个好的/可靠的方法。据我从文档中可以看出,添加排序不会使其预查询所有 ID;如果是这样,那很好,但是我不知道为什么它会解决问题。

在更改内容时使用游标只是一个坏主意吗?

如果这很重要,我正在使用 Scala/Cas​​bah。

4

2 回答 2

8

听起来您想要的是快照查询。以下是有关如何执行此操作的更多信息:

http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database

于 2012-04-17T21:58:56.447 回答
1

考虑使用update修改多个文档的命令:http: //docs.mongodb.org/manual/tutorial/modify-documents/

此外,由于您只修改一些对象,因此请考虑使用只返回您实际要修改的文档的查询,而不是扫描整个集合。

迭代 a 的结果find和修改对象可能看起来更方便和灵活,因为您不限于使用更新运算符可以做什么,您可以用您选择的语言编写代码来修改文档。但是,存在您描述的问题以及其他限制:

http://docs.mongodb.org/manual/faq/developers/#faq-developers-isolate-cursors

例如,快照查询不是 100% 安全的,它们不能与分片集合一起使用,所以如果你后来决定分片,那么你的解决方案就会失败。

如果您需要以更复杂的方式修改大量对象,也许 map-reduce 或聚合管道可以解决您的问题:

http://docs.mongodb.org/manual/core/aggregation-pipeline/

http://docs.mongodb.org/manual/core/map-reduce/

于 2014-08-01T09:28:57.163 回答