【问题标题】:MongoDB NodeJS Native cursor closing prematurelyMongoDB NodeJS 本机游标过早关闭
【发布时间】:2014-05-28 15:33:29
【问题描述】:

我正在对 ursor 的每个元素执行一个过程,我的集合有大约 600 万个文档,整个过程最多需要 10 个小时,因为我必须一次处理一个配置文件,而且对于每一个。

 var cursor = dbMain.collection("profiles").find({});

 var getNext = function(){
      cursor.nextObject(processOne);
 };

 var processOne = function(err, profile){
      if(err){
           console.error("Error loading profile", err);
           getNext();
      } else if(profile == null){
           // process is done, all profiles processed!!!
      } else {
           processProfile(profile)
               .then(function(){
                    getNext();
               })
               .catch(function(errProfile){
                    console.error("Error processing profile", errProfile);
                    getNext();
               });
      }
 };

 var processProfile = function(profile){
      // Complex profile processing and promise resolve when done
 };

 getNext();

问题:当我大约有 300,000 个配置文件时,我得到 null(这意味着光标已用尽),因此,只有前 300,000 个左右得到处理。 ¿ 任何人都知道如何处理它或我提前获得 null 的原因?

【问题讨论】:

  • 我希望你的系统是 64 位的,对吧?
  • 是的,没问题,没有硬件或安装问题。

标签: node.js mongodb database-cursor


【解决方案1】:

对于在最新的 MongoDB 驱动程序上偶然发现此驱动程序的任何人,请注意以下事项。如果您在最后一次调用.next() 之后调用两次.hasNext(),您将得到:Error: Cursor is closed

例如:

while(await cursor.hasNext()) {
    await cursor.next();
}

if (await cursor.hasNext()) {} // Error!

if (!cursor.isClosed() && await cursor.hasNext()) {} // Correct way

【讨论】:

  • 我在使用 for..of 时也遇到了“光标已关闭”的问题,感谢您提供此信息,是否记录在案?
  • 我遇到了同样的错误,正如你所说,我调用了两次方法,不是hasNext(),而是方法.next()。感谢您指出此代码错误。
【解决方案2】:

看来我已经找到原因了:

由于它是一个需要长时间存活的光标,所以在查找选项中我不得不添加“超时:假”。

 var cursor = dbMain.collection("profiles").find({}, {timeout : false});

driver documentation 中说默认情况下它是假的(当然不是!!),现在我所有的个人资料都得到了处理。

【讨论】:

  • 嘿,伙计,我看了源码,终于找到了代码:if(typeof newOptions.timeout == 'boolean') newOptions.noCursorTimeout = newOptions.timeout;if(self.s.options.noCursorTimeout == true) { self.addCursorFlag('noCursorTimeout', true); },意思是只有将timeout指定为true,驱动将发送 noCursorTimeout 标志。所以我不知道你为什么这么做
【解决方案3】:

我遇到了同样的问题,我通过将光标的每个文档推送到列表上然后返回列表来解决它,如下所示:

const list:any= [];
const cursor= await client.db('insertYourDb').collection('insertYourCollection').find().forEach(function(document) { 
        list.push(document) 
    });
return list;

【讨论】:

  • 这将是一个非常糟糕的主意,因为您将耗尽内存。它与执行 find().toArray() 相同,只是要慢得多。
猜你喜欢
  • 2018-12-04
  • 2020-10-27
  • 2018-03-12
  • 2015-02-08
  • 2014-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-22
相关资源
最近更新 更多