Node.js mongodb在遍历大型数据库时停止

Node.js mongodb在遍历大型数据库时停止,node.js,mongodb,Node.js,Mongodb,这是此Stackoverflow问题的后续问题:。这次的转弯稍微有点不同 在MunGDB文档上迭代时,如果目标DB大小过大,任务将停止在中间。(单个集合中有3000多个文档,每个文档都包含很长的文本,因此。由于内存限制,toArray实际上不可行。3000只是整个数据的一部分,完整数据可能超过10000个文档。)我注意到,如果集合中的文档数大于大约750,它只停留在任务的中间。 我搜索了以前的Stackoverflow问题来解决这个问题:有人说,在大型集合上迭代需要使用流,每个或映射,而不是使用

这是此Stackoverflow问题的后续问题:。这次的转弯稍微有点不同

在MunGDB文档上迭代时,如果目标DB大小过大,任务将停止在中间。(单个集合中有3000多个文档,每个文档都包含很长的文本,因此

。由于内存限制,toArray
实际上不可行。3000只是整个数据的一部分,完整数据可能超过10000个文档。)我注意到,如果集合中的文档数大于大约750,它只停留在任务的中间。

我搜索了以前的Stackoverflow问题来解决这个问题:有人说,在大型集合上迭代需要使用
每个
映射
,而不是使用
光标
。当我在现实生活中尝试这些建议时,没有一个能奏效。它们也只是停留在中间,与<>代码> /<代码>迭代几乎没有区别。我真的不喜欢扩展
timeout
的想法,因为它可能会使
光标在内存中四处漂移,但也不起作用

下面的每个方法都处于
async
条件下

流方法

const cursor = db.collections('mycollection').find()
cursor.on('data', doc => {
  await doSomething(doc)//do something with doc here
})
while/for方法(只需将
while
替换为
for

map/each/foreach方法(将
map
替换为
foreach/each

它们之间没有任何区别。当它迭代大约750个文档时,它们就会停止,然后挂起。我甚至尝试在
Promise.all
上注册每个文档,稍后立即执行
async/await
任务,这样游标在迭代时不会花费太多时间,但同样的问题也会出现

编辑:我认为
doSomething()
会让其他读者感到困惑。因此,我创建了一个示例代码,这样您就可以重现这个问题

const MongoClient = require('mongodb').MongoClient
const MongoUrl = 'mongodb://localhost:27017/'
const MongoDBname = 'testDB'
const MongoCollection = 'testCollection'
const moment = require('moment')

const getDB = () =>
  new Promise((resolve,reject)=>{
    MongoClient.connect(MongoUrl,(err,client)=>{
      if(err) return reject(err)
      console.log('successfully connected to db')
      return resolve(client.db(MongoDBname))
      client.close()
    })
  })

;(async ()=>{
  console.log(`iteration begins on ${moment().format('YYYY/MM/DD hh:mm:ss')} ------------`)
  let db = await getDB() //receives mongodb

  //iterate through all db articles...
  const cursor = await db.collection(MongoCollection).find()
  const maxDoc = await cursor.count()
  console.log('Amount of target document:' + maxDoc)
  let count = 0
  //replace this with stream/while/map...any other iteration methods
  cursor.each((err,doc)=>{
    count ++
    console.log(`preloading doc No.${count} async ${(count / maxDoc * 100).toFixed(2)}%`)
  })
})()

我的道歉。在试运行中。它实际上迭代了所有文档…我想我真的对其他部分做了一些错误。我将用引起麻烦的其他部分详细说明这一点。

什么是
doSomething()
实际在做什么?这里最大的可能性是,实际上是代码导致了问题。还要注意的是,无论是
.map()
还是“stream”方法实际上都没有在每次迭代中“等待”,因为每次都缺少所需的步骤。但对于初学者来说,让我们确保即使是
doSomething()
这一点也无法以更好的方式实现。也许可以,你说得对
.map()
或上面的
并不真正等待
异步调用。如果引起混乱,很抱歉。但是,当我尝试在没有实际的
doSomething()
的情况下,使用
console.log()
或此迭代本身的任何其他测试方法对其进行调试时,进度仍然会在类似的点停止。正如我上面提到的,我甚至使用了
Promise
来避免由于
wait
而造成的任何延迟,但同样的问题仍然发生。我的函数可能有问题,但光标一开始甚至没有到达终点。没有“你错了”,因为两者实际上都有等待“下一次循环迭代”的方法,只是你的解释错了。我要你做的,也是解决你问题的唯一方法,就是实际“展示
doSomething()
code正在做什么”。几乎可以肯定,您在代码中做了一些错误的事情,并且很可能没有等待代码中的回调或承诺。简言之,你得出了一个错误的结论,即这与“光标”有关,而这不是真正的问题。对不起,我不明白这一点。除了日志记录(
console.log()
)和计数(
count++
)之外,我确实删除了所有其他部分,以检查我是否对
doSomething()
做了任何错误,它仍然会在类似点停止。当没有实际可用的函数时,我对函数做了什么错误????我将使用示例编辑帖子,这样您就可以在不使用
doSomething()的情况下重现问题。在实际程序完成之前,您正在关闭连接
client.close()
。另外,只需简单地
const client=wait MongoClient.connect(MongoUrl)
,并在正常范围内执行此操作。你的整个“连接功能”基本上是有缺陷的。实际上,我给了你代码,在你的最后一个问题上清楚地显示了这一点。我建议你再复习一遍。
const cursor = db.collections('mycollection').find()
cursor.map(async doc=>{
  await doSomething(doc)
})
const MongoClient = require('mongodb').MongoClient
const MongoUrl = 'mongodb://localhost:27017/'
const MongoDBname = 'testDB'
const MongoCollection = 'testCollection'
const moment = require('moment')

const getDB = () =>
  new Promise((resolve,reject)=>{
    MongoClient.connect(MongoUrl,(err,client)=>{
      if(err) return reject(err)
      console.log('successfully connected to db')
      return resolve(client.db(MongoDBname))
      client.close()
    })
  })

;(async ()=>{
  console.log(`iteration begins on ${moment().format('YYYY/MM/DD hh:mm:ss')} ------------`)
  let db = await getDB() //receives mongodb

  //iterate through all db articles...
  const cursor = await db.collection(MongoCollection).find()
  const maxDoc = await cursor.count()
  console.log('Amount of target document:' + maxDoc)
  let count = 0
  //replace this with stream/while/map...any other iteration methods
  cursor.each((err,doc)=>{
    count ++
    console.log(`preloading doc No.${count} async ${(count / maxDoc * 100).toFixed(2)}%`)
  })
})()