2016-10-10 39 views
0

我有一个NodeJS应用程序,它应该以同步方式(多个嵌套的for-loops)生成大量数据集。这些数据集应该保存到我的MongoDB数据库中,以便稍后更有效地查找它们。NodeJS只写入MongoDB一次

我为NodeJS使用mongodb驱动程序并运行一个守护进程。与数据库的连接工作正常,根据守护进程窗口,第一组数据集正在成功存储。每〜400-600毫秒都有另一组存储,但是在第一个数据集之后,MongoDB控制台中不再有输出(甚至没有错误),并且由于文件大小没有增加,我假设这些写入操作不起作用(我不能等待它完成,因为它需要几天才能完全运行)。

如果我重新启动NodeJS脚本,它甚至不会保存第一个键,可能是因为重复?如果我删除数据库文件夹的内容,第一个将再次保存。

这是我的脚本的重要组成部分,我无法找到任何我做错了。我认为问题更多的是在内部逻辑(奇怪的重复检查/不运行并发等)。

var MongoClient = require('mongodb').MongoClient, dbBuffer = []; 
MongoClient.connect('mongodb://127.0.0.1/loremipsum', function(err, db) { 
    if(err) return console.log("Cant connect to MongoDB"); 
    var collection = db.collection('ipsum'); 
    console.log("Connected to DB"); 

    for(var q=startI;q<endI;q++) { 
     for(var w=0;w<words.length;w++) { 
      dbBuffer.push({a:a, b:b}); 
     } 
     if(dbBuffer.length) { 
      console.log("saving "+dbBuffer.length+" items"); 
      collection.insert(dbBuffer, {w:1}, function(err, result) { 
       if(err) { 
        console.log("Error on db write", err); 
        db.close(); 
        process.exit(); 
       } 
      }); 
     } 
     dbBuffer = []; 
    } 
    db.close(); 
}); 

更新

  • db.close不会被调用和连接不降
  • 更改为批量插入的插入是不会改变任何东西
  • 回调从来没有叫 - 这可能是问题! MongoDB控制台确实告诉我,插入过程是成功的,但看起来驱动程序和MongoDB之间的通信不能正常工作以便插入。
+1

'collection.insert'是一个异步调用,所以在那些完成你最后的'db.close()'调用发生。 – JohnnyHK

+0

另外,对于[Bulk.insert](https://docs.mongodb.com/manual/reference/method/Bulk.insert/)(而不是dbBuffer阵列攻击),这是一个很好的用例 –

+0

@JohnnyHK如上所述,这是实际运行多天的多个嵌套循环的简化示例。我可以在MongoDB控制台看到连接没有关闭。菲利普:你说得对,我会试试看,但它确实不是一个很大的区别。 –

回答

0

我自己“解决”了它。我有一个误解,那就是每个插入事务都在MongoDB控制台中得到确认,而实际上只确认了第一个,或者在这两个命令之间有一段时间。要检查插入过程是否真的有效,需要运行脚本一段时间,并等待MongoDB将其转储到本地文件(大约30-60s)。

另外,插入过程相互之间过快,MongoDB在Win10 x64下似乎无法正确处理。我从阵列缓冲区更改为内部缓冲区(请参阅注释),并且只能在插入先前数据后继续进行。

这是简化的结果代码

db.collection('seedlist', function(err, collection) { 
    syncLoop(0,0, collection); 
    //... 
}); 

function syncLoop(q, w, collection) { 
    batch = collection.initializeUnorderedBulkOp({useLegacyOps: true}); 
    for(var e=0;e<words.length;e++) { 
     batch.insert({a:a, b:b}); 
    } 
    batch.execute(function(err, result) { 
     if(err) throw err; 
     //... 
     return setTimeout(function() { 
      syncLoop(qNew,wNew,collection); 
     }, 0); // Timer to prevent Memory leak 
    }); 
}