mongodb - MongoDB批量FindAndModify的解决方案

我的用例如下 - 我在 mongoDB 中有一组文档,我必须发送这些文档进行分析。 文件格式如下-

{ _id:ObjectId("517e769164702dacea7c40d8") , 日期:“1359911127494”, 状态:“可用”, 其他字段... }

我有一个阅读器进程,它选择按 date 排序的 status:available 的前 100 个文档,并使用 status:processing 修改它们。 ReaderProcess 发送文档进行分析。分析完成后,status 将更改为 processed

当前阅读器进程首先获取 100 个按 date 排序的文档,然后在循环中将每个文档的 status 更新为 processing。这种情况有没有更好/更有效的解决方案?

此外, future 为了可扩展性,我们可能会使用多个读取器进程。 在这种情况下,我希望一个阅读器进程选择的 100 个文档不应该被另一个阅读器进程选择。但是现在获取和更新是单独的查询,所以很可能多个读取器进程选择相同的文档。

Bulk findAndModify(有限制)可以解决所有这些问题。但不幸的是,它还没有在 MongoDB 中提供。这个问题有解决办法吗?

最佳答案

正如你提到的,目前没有干净的方法可以做你想做的事。目前,对于您需要的操作,最好的方法是:

  1. 阅读器选择 X 个具有适当限制和排序的文档
  2. Reader 用自己唯一的 Reader ID (e.g. update({_id:{$in:[<result set ids>]}, state:"available", $isolated:1}, {$set:{readerId:<your reader's ID>, state:"processing"}}, false, true)) 标记 1) 返回的文档
  3. 阅读器选择所有标记为正在处理且具有自己阅读器 ID 的文档。此时可以保证您拥有对生成的文档集的独占访问权限。
  4. 提供来自 3) 的结果集供您处理。

请注意,这甚至适用于高度并发的情况,因为阅读器永远无法保留尚未被其他阅读器保留的文档(请注意,步骤 2 只能保留当前可用的文档,并且写入是原子的)。如果您希望能够使预订超时(例如对于阅读器可能崩溃/失败的情况),我也会添加一个带有预订时间的时间戳。

编辑:更多细节:

如果写入需要相对较长的时间,则所有写入操作偶尔会为挂起的操作生成。这意味着除非您采取以下步骤,否则步骤 2) 可能看不到步骤 1) 标记的所有文档:

  • 使用适当的“w”(写关注)值,表示 1 或更高。这将确保调用写入操作的连接将等待它完成,而不管它是否产生。
  • 确保在同一连接(仅与启用了 slaveOk 读取的副本集相关)或线程上执行步骤 2 中的读取,以保证它们是连续的。前者可以在大多数驱动程序中使用“requestStart”和“requestDone”方法或类似方法来完成(Java 文档here)。
    • 将 $isolated 标志添加到您的多重更新中,以确保它不会与其他写入操作交错。

另请参阅有关原子性/隔离性讨论的评论。我错误地认为多重更新是孤立的。它们不是,或者至少默认情况下不是。

https://stackoverflow.com/questions/16334045/

相关文章:

mongodb - 当父字段未知时,在嵌套文档中查找具有字段的记录

mongodb - Spark 流 : foreachRDD update my mongo RDD

performance - 字段类型在 MongoDB 索引中是否重要?

javascript - MongoError : cannot change _id of a d

ruby-on-rails - MongoDB 的最佳分析/数据可视化库

mongodb - 在集合之间移动文档是表示 MongoDB 中状态变化的好方法吗?

javascript - Mongoose 连接到 MongoDB Atlas 的最佳池大小是多少?

javascript - 在 MongoDB 中按字母顺序对文档进行排序(也称为自然排序顺序,人类排

mongodb - 在mongo聚合中将ObjectID转换为字符串

mongodb - Azure:不支持 DocumentDB Mongo $group