5

私は mongoDB を使用する node.js アプリケーションを持っており、コレクション内のすべてのドキュメントを削除してから、データベース内のコレクションにいくつかのサンプル ドキュメントを再設定する関数があります。

これを使用して、新しい機能を作成するときに、既知のデータでアプリをテストすることがあります。

私が遭遇する問題は、すべてのコレクションで drop() を呼び出してから、いくつかの挿入を呼び出して再作成すると、データベースに挿入されると予想されるよりもレコードが少なくなり、コレクション全体が失われることがあります。私のカウントチェックはすべて、予想される量と一致する # レコードが挿入されたと言っていますが、挿入されたと表示されていても、コレクション全体が欠落している可能性があります。

drop() が完了する前に何らかの方法で挿入が挿入を開始し、非同期で実行されているために drop() が挿入されたドキュメントを消去するのは約 50% の時間しか発生しないため、私は推測できます。

すべての挿入/更新コマンドで {safe:true} を使用していますが、db.collection.drop() は引数をとらず、安全なオプションを指定する方法がないようです。

そのため、drop() の後に db.getLastError() を使用して、ドロップが完了するまで挿入をブロックしようとしています。

db.getLastError() または db.getlasterror() を使用するとエラーがスローされます: TypeError: Object #<Db> has no method '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 のコード サンプルの getlasterror で、stackoverflow または web で一般的に何も見つかりません。

これを行うためのより良い方法があれば、私はすべて耳にします。

js ドキュメント: http://docs.mongodb.org/manual/reference/javascript/#db.getLastError

モンゴのドキュメント: http://www.mongodb.org/display/DOCS/getLastError+Command

---- 2012 年 9 月 22 日更新

以下の回答を使用して、根本的な問題が何であるかを少しデバッグすることができました。それは期待どおりです。5 つの開いている接続のデフォルトの接続プールでは、ドロップがランダムに開始され、その後に挿入が続きます。送信される順序とそれぞれが移動するプールに応じて、1 つのドロップがすばやく終了し、そのコレクションのドロップが終了する前にすばやく挿入を行うと、挿入されたレコードが後で削除されます。

私の修正は、drop() コマンドのコールバック内の連鎖シーケンスですべてのドロップをラップすることでした。これにより、各ドロップは、前のドロップのコールバックが起動された後に発生し、最後にすべての挿入を起動するコールバックが呼び出されます。面倒ですが、20 の単純な挿入の基本レコード セットと 100,000 レコードの負荷テストを使用して、initializeddb 関数を約 25 回テストしました。まだ失敗はありません。

時間が経てばわかりますが、この .lastError() の回答はこの問題を解決するために機能しました。

---- 2012 年 9 月 30 日更新

実際に機能することを確認するために返信する前に、これを 1 週間ほどテストしたかったのです。先週、26 レコードの基本セットと、すべて一括挿入される 100,000 レコードのセットの両方で、初期化スクリプトを約 100 回実行しました。新しいコードを使用して一度も失敗したことはありません。

コレクションを削除するために使用するコード: (操作用のプロトタイプ関数で使用する DatabaseHandler オブジェクトがあります)

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 が呼び出され、コールバックの初期化関数が使用されます。そのため、ドロップが終了すると、初期化コールバックが呼び出され、ドロップが終了した後にのみドキュメントの再追加が開始されます。また、挿入が完了した後に挿入されたドキュメントの数をチェックして、正しい数が挿入され、見逃されていないことを確認する小さなカウント機能もあります。これはおそらく私が追加した最高の機能だったので、初期化するたびに、挿入されたドキュメントの正確な数が正しいか、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);
}

それが役立つことを願っています

4

1 に答える 1

1

node-mongodb-native ドライバーを使用していますか? その場合は、lastError コマンドを見てください。

http://mongodb.github.com/node-mongodb-native/api-generated/db.html#lasterror

于 2012-09-21T16:55:13.980 に答える