2012-09-21 21 views
4

我有一個使用mongoDB的node.js應用程序,我有一個函數用於刪除集合中的所有文檔,然後重新填充我的數據庫中的集合一些樣本文件。mongoDB getLastError()javascript和node.js不工作

當我編寫新功能時,我曾用它在已知數據中測試過我的應用程序。

我碰到的問題是,如果我在我所有的集合上調用drop(),然後調用一些插入來重新填充,有時我會有比我期望插入數據庫的記錄更少的記錄,有時整個集合將會失蹤。我的計數會檢查所有插入的符合預期金額的#個記錄,但是即使它已插入,整個集合也可能會丟失。

我只能假設,因爲它只發生大約50%的時間,或許某種程度上插入開始在drop()完成之前插入,然後drop()由於其正在運行的異步而刪除插入的文檔。

我在所有插入/更新命令中使用{safe:true},但db.collection.drop()不帶任何參數,似乎無法指定安全選項。

所以我試圖在drop()之後使用db.getLastError()來阻塞插入,直到刪除完成。

使用db.getLastError()或db.getlasterror()拋出一個錯誤: 類型錯誤:對象#< Db的>沒有方法 'GetLastError函數'

簡化呼叫到GetLastError函數:

var mongo = require("mongodb"); 

    var db_conn = new mongo.Db(dbName, new mongo.Server(host, port, { auto_reconnect: true }), {}); 
    db_conn.open(function(err, db) { 
    if(!err) { 
     console.log("Database connection: \033[32mopen\033[0m"); 
    } else { 
     console.log("Database connection: \033[31mfailed\033[0m"); 
    } 
    }); 
    db_conn.getLastError(); 
    this.db_conn = db_conn; 
    this.users = db_conn.collection("users"); 
    this.companies = db_conn.collection("companies"); 
    this.suppliers = db_conn.collection("suppliers"); 

我已經在mongodb模塊版本1.1.4和1.1.7上試過了,只是出現錯誤。

我使用的是錯誤的引用嗎?我在JavaScript中的代碼示例中找不到任何關於stackoverflow或web上的getlasterror。

如果有更好的方法來做到這一點,我全部耳朵。

JS文檔:http://docs.mongodb.org/manual/reference/javascript/#db.getLastError

蒙戈文檔:http://www.mongodb.org/display/DOCS/getLastError+Command

---- UPDATE 2012年9月22日

使用下面的回答,我能夠調試了一下問題的根源是什麼,它的如我所料。使用5個打開連接的默認連接池,墨滴會隨機發射,然後隨即插入。根據它們發送的順序以及它們各自到達的池,如果一個子快速完成,然後在該子集的刪除完成之前快速插入,它將在稍後刪除插入的記錄。

我的修補程序是在drop()命令的回調中將所有的下降包裝在一個鏈接序列中,以便每次下降發生在上一個下拉的回調被觸發後,然後在最後調用一個回調所有的插入。這很麻煩,但我已經使用20個簡單插入的基本記錄集和100,000個記錄的加載測試測試了初始化的b函數現在約25次。沒有失敗。

時間會告訴,但這個.lastError()答案工作來解決這個問題。

---- UPDATE 2012年9月30日

我想回響應,以確保它的實際工作之前測試這一個星期左右。我已經在上週運行了我的初始化腳本約100次,包括26個記錄的基本集合和100,000個記錄全部被批量插入。我還沒有看到它現在使用我的新代碼失敗了。

代碼我用丟棄集合:(我有我的原型功能操作使用一個數據庫處理器對象)

DatabaseHandler.prototype.dropAll = function(callback, callbackArg) { 
    // drop all the documents 
    var that = this; 
    var finished = callback || function() { }; 
    var finishedArg = callbackArg; 
    this.companies.drop(function(err, reply) { 
    if(reply) { 
     console.log("[db] Companies collection dropped"); 
    } else { 
     console.log("\033[31m[Error]\033[0m Companies collection failed to drop"); 
    } 
    // drop all the user documents 
    that.users.drop(function(err, reply) { 
     if(reply) { 
     console.log("[db] Users collection dropped"); 
     } else { 
     console.log("\033[31m[Error]\033[0m Users collection failed to drop"); 
     } 
     // drop all the course documents 
     that.courses.drop(function(err, reply) { 
     if(reply) { 
      console.log("[db] Courses collection dropped"); 
     } else { 
      console.log("\033[31m[Error]\033[0m Courses collection failed to drop"); 
     } 
     // drop all the course purchase documents 
     that.course_purchases.drop(function(err, reply) { 
      if(reply) { 
      console.log("[db] Course purchases collection dropped"); 
      } else { 
      console.log("\033[31m[Error]\033[0m Course purchases collection failed to drop"); 
      } 
      console.log("Dropped all documents and collections"); 
      return finished(finishedArg); 
     }); 
     }); 
    }); 
    }); 
}; 

然後我有一個初始化函數,它的參數來指定,如果我想額外負擔測試數據初始化(addloadtestdata)。如果我指定dropdata,它將調用dropAll並將初始化函數用於回調。所以當放置完成時,它會調用initialize回調,並在文檔完成刪除後纔開始重新添加文檔。 我還有一個小計數功能,可以在完成插入操作後檢查插入了多少個文檔,以驗證插入了正確的數字,並且沒有錯過。這可能是我添加了所有最好的功能,使我每次初始化時間,我可以看到,如果插入的文件的確切數字是正確的,或者如果我失去了甚至1.

function initialize(doLoadtest){ 
    // do work here 
} 
// drop all collections and documents 
if(dropdata) { 
    // drop all the data first then call the initialize as a callback function when completed dropping 
    Database.dropAll(initialize, includeLoadtestData); 
} else { 
    initialize(includeLoadtestData); 
} 

希望幫助

+0

我有一個類似的問題,當我跑我的摩卡測試。這絕對是一個時間問題。我也設置了'{safe:true}',但似乎沒有太大區別。我放了1秒的setTimeout來解決這個問題(只在測試中)。現在它工作的時間有95%。 – c0deNinja

+0

你可以發佈你最終使用的代碼嗎? – c0deNinja

+0

上面加了代碼示例 – Dhodgin

回答