15

node.jsを理解するのに問題があります。

例、MongoDBアクセス、これが私が持っているものです(mydb.js):

var mongodb = require('mongodb'),
    server = new mongodb.Server('staff.mongohq.com', 10030, {
        auto_reconnect: true
    }),
    db = new mongodb.Db('mydb', server);

function authenticateAndGo(db, handle) {
    db.authenticate('username', 'password', function(err) {
        if (err) {
            console.log(err);
            return;
        }
        console.log('Database user authenticated');

        var collection = new mongodb.Collection(db, 'test');

        handle(collection);
    });
}

function query(handle) {
    db.open(function(err, db) {
        if( err ) {
            console.log(err);
            return;
        }
        console.log('Database connected');

        authenticateAndGo(db, handle);
    });
};
exports.query = query;

だから、後で使いたいのなら、

var mydb = require('./mydb');
mydb.query(function(collection) {
    collection.find({}, {
        limit: 10
    }).toArray(function(err, docs) {
        console.log(docs);
    });
});

しかし、次のように複数の呼び出しを行う場合:

var mydb = require('./mydb');
mydb.query(function(collection) {
    collection.find({}, {
        limit: 10
    }).toArray(function(err, docs) {
        console.log(docs);
    });
});
mydb.query(function(collection) {
    collection.find({}, {
        limit: 10
    }).toArray(function(err, docs) {
        console.log(docs);
    });
});

例外が発生します:

Error: db object already connecting, open cannot be called multiple times

私はこれらすべてについて私が理解していない根本的な何かが本当にあると思います、そしてこの質問は愚かである可能性があります...

とにかく、すべての助けは大歓迎です。

前もって感謝します。

4

3 に答える 3

10

mydb.js

var mongodb= require('mongodb'),
  server = new mongodb.Server('staff.mongohq.com', 10030, {
    auto_reconnect: true
  }),
  db1 = new mongodb.Db('mydb', server);


// callback: (err, db)
function openDatabase(callback) {
  db1.open(function(err, db) {
    if (err)
      return callback(err);

    console.log('Database connected');

    return callback(null, db);
  });
}

// callback: (err, collection)
function authenticate(db, username, password, callback) {
  db.authenticate(username, password, function(err, result) {
    if (err) {
      return callback (err);
    }
    if (result) {
      var collection = new mongodb.Collection(db, 'test');

      // always, ALWAYS return the error object as the first argument of a callback
      return callback(null, collection);
    } else {
      return callback (new Error('authentication failed'));
    }
  });
}

exports.openDatabase = openDatabase;
exports.authenticate = authenticate;

use.js

var mydb = require('./mydb');
// open the database once
mydb.openDatabase(function(err, db) {
  if (err) {
    console.log('ERROR CONNECTING TO DATABASE');
    console.log(err);
    process.exit(1);
  }

  // authenticate once after you opened the database. What's the point of 
  // authenticating on-demand (for each query)?
  mydb.authenticate(db, 'usernsame', 'password', function(err, collection) {
    if (err) {
      console.log('ERROR AUTHENTICATING');
      console.log(err);
      process.exit(1);
    }

    // use the returned collection as many times as you like INSIDE THE CALLBACK
    collection.find({}, {limit: 10})
    .toArray(function(err, docs) {
      console.log('\n------ 1 ------');
      console.log(docs);
    });

    collection.find({}, {limit: 10})
    .toArray(function(err, docs) {
      console.log('\n------ 2 ------');
      console.log(docs);
    });
  });
});

結果:

成功時:

 Database connected
 Database user authenticated

------ 1 ------
[ { _id: 4f86889079a120bf04e48550, asd: 'asd' } ]

------ 2 ------
[ { _id: 4f86889079a120bf04e48550, asd: 'asd' } ]

失敗時:

Database connected
{ [MongoError: auth fails] name: 'MongoError', errmsg: 'auth fails', ok: 0 }

[元の回答]:

db複数回開いています(それぞれに1回query)。データベースを一度だけ開いて、db後で使用するためにコールバックでオブジェクトを使用する必要があります。

同じ変数名を複数回使用しているため、混乱が生じている可能性があります。

var mongodb = require('mongodb'),
    server = new mongodb.Server('staff.mongohq.com', 10030, {
        auto_reconnect: true
    }),
    db1 = new mongodb.Db('mydb', server);

function authenticateAndGo(db, handle) {
    db.authenticate('username', 'password', function(err) {
        if (err) {
            console.log(err);
            return;
        }
        console.log('Database user authenticated');

        var collection = new mongodb.Collection(db, 'test');

        handle(collection);
    });
}

function query(handle) {
    db1.open(function(err, db2) {
        if( err ) {
            console.log(err);
            return;
        }
        console.log('Database connected');

        authenticateAndGo(db2, handle);
    });
};
exports.query = query;

上記のコードを少し変更しました(db1元のデータベースのdb2場合、開いたデータベースの場合)。ご覧のとおり、db1何度も開いていますが、これは良くありません。db2別のメソッドを開くためのコードを抽出し、それを1回使用して、すべてのクエリ/更新/削除/...にインスタンスを使用します。

于 2012-04-11T14:47:38.130 に答える
8

「オープン」を呼び出すことができるのは1回だけです。openコールバックが起動すると、返されたDBオブジェクトに対してクエリを実行できます。したがって、これを処理する1つの方法は、オープンが完了するまでリクエストをキューに入れることです。例:MyMongo.js

var mongodb = require('mongodb');

function MyMongo(host, port, dbname) {
    this.host = host;
    this.port = port;
    this.dbname = dbname;

    this.server = new mongodb.Server(
                              'localhost', 
                              9000, 
                              {auto_reconnect: true});
    this.db_connector = new mongodb.Db(this.dbname, this.server);

    var self = this;

    this.db = undefined;
    this.queue = [];

    this.db_connector.open(function(err, db) {
            if( err ) {
                console.log(err);
                return;
        }
        self.db = db;
        for (var i = 0; i < self.queue.length; i++) {
            var collection = new mongodb.Collection(
                                 self.db, self.queue[i].cn);
            self.queue[i].cb(collection);
        }
        self.queue = [];

    });
}
exports.MyMongo = MyMongo;

MyMongo.prototype.query = function(collectionName, callback) {
    if (this.db != undefined) {
        var collection = new mongodb.Collection(this.db, collectionName);
        callback(collection);
        return;
    }
    this.queue.push({ "cn" : collectionName, "cb" : callback});
}

次に、サンプルの使用:

var MyMongo = require('./MyMongo.js').MyMongo;

var db = new MyMongo('localhost', 9000, 'db1');
var COL = 'col';

db.query(COL, function(collection) {
    collection.find({}, {
        limit: 10
    }).toArray(function(err, docs) {
        console.log("First:\n", docs);
    });
});


db.query(COL, function(collection) {
    collection.find({}, {
        limit: 10
    }).toArray(function(err, docs) {
        console.log("\nSecond:\n", docs);
    });
});
于 2012-04-11T17:40:45.853 に答える
1

dbinitの直後にopen関数を1回呼び出すだけです。

var mongodb = require('mongodb');
var server = new mongodb.Server('foo', 3000, {auto_reconnect: true});
var db = new mongodb.Db('mydb', server);   
db.open(function(){});

その後、auto_reconnectがtrueであるため、これについてはもう気にする必要はありません。

db.collection('bar', function(err, collection) { [...] };
于 2012-07-17T08:10:53.930 に答える