Mongoose如何连接到许多数据库

时间:2021-03-29 02:33:57

For a project, I need to switch between some MongoDB databases for doing some queries.

对于一个项目,我需要在一些MongoDB数据库之间切换以进行一些查询。

I found some exemple like that one : Mongoose and multiple database in single node.js project

我发现了一个例子:Mongoose和单个node.js项目中的多个数据库

His answer is perfectly working but now I'm trying to do it in a loop and unfortunally it's not work, I get this error:

他的答案完全正常,但现在我试图在一个循环中这样做,不幸的是它不起作用,我得到这个错误:

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: failed to connect to [localhost:27017]
    at null.<anonymous> (/home/user/test_many_db_mongodb/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/server.js:549:74)
    at EventEmitter.emit (events.js:106:17)
    at null.<anonymous> (/home/user/test_many_db_mongodb/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:150:15)
    at EventEmitter.emit (events.js:98:17)
    at Socket.<anonymous> (/home/user/test_many_db_mongodb/node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js:533:10)
    at Socket.EventEmitter.emit (events.js:95:17)
    at net.js:440:14
    at process._tickCallback (node.js:419:13)

And I don't understand why I get this error, if the example in the link above work my code should too:

我不明白为什么我会收到此错误,如果上面链接中的示例工作我的代码也应该:

var mongoose = require('mongoose');

for (var i = 0; i != 1000; i++) {
    var conn = mongoose.createConnection('mongodb://localhost/test' + i);

    conn.on('connected', function() {
        console.log('Mongoose connected to database');

        var Model    = conn.model('Model', new mongoose.Schema({
            title : { type : String, default : 'model in test database' }
        }));

        var newModelA = new Model();
        newModelA.save(function(err) {
            if (err)
                console.log(err);
            console.log('save A');
        });
    });
}

Thanks for your help.

谢谢你的帮助。

3 个解决方案

#1


1  

I think there is a problem with for loop. Because the code inside the loop is asynchronous in nature. So I have used forEach instead of for. Please take a look at the following code. It works fine for me.

我认为for循环存在问题。因为循环内部的代码本质上是异步的。所以我用过forEach而不是for。请查看以下代码。这对我来说可以。

var mongoose = require('mongoose'),
    arr = [0, 1, 2];

arr.forEach(function(i) {
    var conn = mongoose.createConnection('mongodb://localhost/test' + i);

    conn.on('connected', function() {
        console.log('Mongoose connected to database', i);

        var Model = conn.model('Model', new mongoose.Schema({
            title: {
                type: String,
                default: 'model in test database'
            }
        }));

        var newModelA = new Model();
        newModelA.save({
            name: 'a'
        }, function(err) {
            if (err)
                console.log(err);
            console.log('save A');
        });
    });
});

I have does this for three times. You can do it for 1000 times also.

我这样做了三次。你也可以做1000次。

#2


1  

You're getting the failed to connect error because you're creating all 1000 database connection pools in a synchronous loop which is exhausting the supply of available MongoDB connections.

您将收到无法连接错误,因为您在同步循环中创建了所有1000个数据库连接池,这会耗尽可用的MongoDB连接。

So you need to introduce some asynchronous flow control to your approach using something like the async library's eachLimit method:

因此,您需要使用async库的eachLimit方法为您的方法引入一些异步流控制:

var mongoose = require('mongoose');
var async = require('async');

var iterations = [];
for (var i = 0; i != 1000; i++) {
    iterations.push(i);
}

// Iterate over iterations, allowing no more than 5 async iterations to be
// outstanding at any one time.
async.eachLimit(iterations, 5, function(i, callback) {
    var conn = mongoose.createConnection('mongodb://localhost/test' + i);

    conn.on('connected', function(err) {
        console.log('Mongoose connected to database');

        var Model = conn.model('Model', new mongoose.Schema({
            title : { type : String, default : 'model in test database' }
        }));

        var newModelA = new Model();
        newModelA.save(function(err) {
            if (err)
                console.log(err);
            console.log('save A');

            // Close the connection and tell eachLimit this iteration is
            // complete by having the close method call the eachLimit callback
            // when the close completes.
            conn.close(callback);
        });    
    });
}, function() {
    console.log('All done!');
});

#3


0  

Thanks for your help.

谢谢你的帮助。

I tried both way but it didn't work on my project, probably because I didn't show you all the code. I found a way using useDb():

我试过两种方式,但它对我的项目不起作用,可能是因为我没有向你展示所有的代码。我找到了一种使用useDb()的方法:

var amqp = require('amqp');

var MailParser = require('mailparser').MailParser;
var mailparser = new MailParser();

var mongoose = require('mongoose');
var conn = mongoose.createConnection('mongodb://localhost');

var count = 1;

var connection = amqp.createConnection({host: 'localhost'});

    connection.on('ready', function() {
        connection.queue('task_queue', {autoDelete: false,
                                        durable: true}, function(queue) {

            console.log('Waiting for emails. To exit press CTRL+C');

            queue.subscribe({ack: true, prefetchCount: 1}, function(message, headers, deliveryInfo, ack) {
                mailparser.write(message.data.toString('utf-8'));
                mailparser.end();

                ack.acknowledge();
            });
        });
    });

mailparser.on("end", function(email_object){
    var d = new Date(); // just for be sure the db name is unique for the test
    var db = conn.useDb('test_'+d.getDate()+'-'+d.getMonth()+'-'+d.getYear()+'_'+d.getHours()+'-'+d.getMinutes()+'-'+d.getSeconds()+'-'+d.getMilliseconds());

    var Model    = conn.model('Model', new mongoose.Schema({
            subject : { type : String },
            body : { type : String }
        }));
    var newEmail = new Model();
    newEmail.subject = email_object.subject;
    newEmail.body = email_object.body;
    newEmail.save(function(err) {
        if (err) console.error(err);
        console.log(count++);
    });
});

#1


1  

I think there is a problem with for loop. Because the code inside the loop is asynchronous in nature. So I have used forEach instead of for. Please take a look at the following code. It works fine for me.

我认为for循环存在问题。因为循环内部的代码本质上是异步的。所以我用过forEach而不是for。请查看以下代码。这对我来说可以。

var mongoose = require('mongoose'),
    arr = [0, 1, 2];

arr.forEach(function(i) {
    var conn = mongoose.createConnection('mongodb://localhost/test' + i);

    conn.on('connected', function() {
        console.log('Mongoose connected to database', i);

        var Model = conn.model('Model', new mongoose.Schema({
            title: {
                type: String,
                default: 'model in test database'
            }
        }));

        var newModelA = new Model();
        newModelA.save({
            name: 'a'
        }, function(err) {
            if (err)
                console.log(err);
            console.log('save A');
        });
    });
});

I have does this for three times. You can do it for 1000 times also.

我这样做了三次。你也可以做1000次。

#2


1  

You're getting the failed to connect error because you're creating all 1000 database connection pools in a synchronous loop which is exhausting the supply of available MongoDB connections.

您将收到无法连接错误,因为您在同步循环中创建了所有1000个数据库连接池,这会耗尽可用的MongoDB连接。

So you need to introduce some asynchronous flow control to your approach using something like the async library's eachLimit method:

因此,您需要使用async库的eachLimit方法为您的方法引入一些异步流控制:

var mongoose = require('mongoose');
var async = require('async');

var iterations = [];
for (var i = 0; i != 1000; i++) {
    iterations.push(i);
}

// Iterate over iterations, allowing no more than 5 async iterations to be
// outstanding at any one time.
async.eachLimit(iterations, 5, function(i, callback) {
    var conn = mongoose.createConnection('mongodb://localhost/test' + i);

    conn.on('connected', function(err) {
        console.log('Mongoose connected to database');

        var Model = conn.model('Model', new mongoose.Schema({
            title : { type : String, default : 'model in test database' }
        }));

        var newModelA = new Model();
        newModelA.save(function(err) {
            if (err)
                console.log(err);
            console.log('save A');

            // Close the connection and tell eachLimit this iteration is
            // complete by having the close method call the eachLimit callback
            // when the close completes.
            conn.close(callback);
        });    
    });
}, function() {
    console.log('All done!');
});

#3


0  

Thanks for your help.

谢谢你的帮助。

I tried both way but it didn't work on my project, probably because I didn't show you all the code. I found a way using useDb():

我试过两种方式,但它对我的项目不起作用,可能是因为我没有向你展示所有的代码。我找到了一种使用useDb()的方法:

var amqp = require('amqp');

var MailParser = require('mailparser').MailParser;
var mailparser = new MailParser();

var mongoose = require('mongoose');
var conn = mongoose.createConnection('mongodb://localhost');

var count = 1;

var connection = amqp.createConnection({host: 'localhost'});

    connection.on('ready', function() {
        connection.queue('task_queue', {autoDelete: false,
                                        durable: true}, function(queue) {

            console.log('Waiting for emails. To exit press CTRL+C');

            queue.subscribe({ack: true, prefetchCount: 1}, function(message, headers, deliveryInfo, ack) {
                mailparser.write(message.data.toString('utf-8'));
                mailparser.end();

                ack.acknowledge();
            });
        });
    });

mailparser.on("end", function(email_object){
    var d = new Date(); // just for be sure the db name is unique for the test
    var db = conn.useDb('test_'+d.getDate()+'-'+d.getMonth()+'-'+d.getYear()+'_'+d.getHours()+'-'+d.getMinutes()+'-'+d.getSeconds()+'-'+d.getMilliseconds());

    var Model    = conn.model('Model', new mongoose.Schema({
            subject : { type : String },
            body : { type : String }
        }));
    var newEmail = new Model();
    newEmail.subject = email_object.subject;
    newEmail.body = email_object.body;
    newEmail.save(function(err) {
        if (err) console.error(err);
        console.log(count++);
    });
});