【问题标题】:NodeJS MongoDB avoid Cursor TimeoutNodeJS MongoDB 避免光标超时
【发布时间】:2018-07-10 19:27:39
【问题描述】:

我想循环抛出我的 MongoDB 的特定集合中的所有文档。但是,由于光标超时,我所做的每一次尝试都失败了。这是我的代码

let MongoClient = require('mongodb').MongoClient;
const url = "my connection URI"
let options = { socketTimeoutMS: 120000, connectTimeoutMS: 120000, keepAlive: 100, poolSize: 5 }

MongoClient.connect(url, options,
  function(err, db) {
  if (err) throw err
  let dbo = db.db("notes")
  let collection = dbo.collection("stats-network-consumption")

  let stream = collection.find({}, { timeout: false }).stream()

  stream.on("data", function(item) {
    printTask(item)
  })

  stream.on('error', function (err) {
    console.error(err)
  })

  stream.on("end", function() {
    console.log("DONE!")
    db.close()
  })

})

上面的代码运行了大约 15 秒,检索了 6000 到 8000 个文档,然后抛出以下错误:

{ MongoError: cursor does not exist, was killed or timed out
    at queryCallback (/Volumes/safezone/development/workspace-router/migration/node_modules/mongodb-core/lib/wireprotocol/2_6_support.js:136:23)
    at /Volumes/safezone/development/workspace-router/migration/node_modules/mongodb-core/lib/connection/pool.js:541:18
    at process._tickCallback (internal/process/next_tick.js:150:11)
  name: 'MongoError',
  message: 'cursor does not exist, was killed or timed out' }

我需要检索大约 50000 个文档,因此我需要找到一种方法来避免光标超时。

如上面的代码所示,我尝试增加socketTimeoutMSconnectTimeoutMS,这对光标超时没有影响。

我也尝试将stream 替换为forEach 并添加.addCursorFlag('noCursorTimeout', true),但这也没有帮助。

我已经尝试了我发现的关于 mongodb 的所有内容,我没有尝试过 mongoose 或替代方案,因为它们使用模式,我稍后必须更新属性的当前类型(这对于 mongoose 模式可能很棘手) .

【问题讨论】:

    标签: node.js mongodb timeout


    【解决方案1】:

    一般不建议使用没有超时的游标。

    原因是,游标永远不会被服务器关闭,因此如果您的应用程序崩溃并重新启动它,它将在服务器上打开另一个无超时游标。经常回收您的应用程序,这些将加起来。

    分片集群上没有超时游标也会阻止块迁移。

    如果您需要检索大结果,游标不应该超时,因为结果将分批发送,并且游标将被重复使用以获取下一批。

    标准游标超时时间为 10 分钟,因此如果您需要超过 10 分钟来处理批处理,则可能会丢失游标。

    在您的代码示例中,您对stream() 的使用可能会干扰您的意图。尝试在光标上使用each() (example here)。

    如果您需要监控集合的更改,您可能需要查看 Change Streams,这是 MongoDB 3.6 中的新功能。

    例如,您的代码可能可以修改如下:

    let collection = dbo.collection("stats-network-consumption")
    let stream = collection.watch()
    document = next(stream)
    

    请注意,要启用更改流支持,您使用的驱动程序必须支持 MongoDB 3.6 功能和 watch() 方法。详情请见Driver Compatibility Page

    【讨论】:

      猜你喜欢
      • 2017-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-10
      相关资源
      最近更新 更多