2016-10-10 65 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 
    }); 
}