Подключение к Mongodb-Native-Driver в express.js

Я использую mongodb-native-driver в приложении express.js. У меня около 6 коллекций в базе данных, поэтому я создал 6 js файлов, каждый из которых имеет коллекцию как объект javascript (например, function collection(){}) и функции прототипов, обрабатывающие все манипуляции с этими коллекциями. Я думал, что это будет хорошая архитектура.

Но проблема, с которой я столкнулась, - это как подключиться к базе данных? Должен ли я создать соединение в каждом из этих файлов и использовать их? Я думаю, что это было бы излишним, поскольку соединение в mongodb-native-driver создает пул соединений, и некоторые из них не будут оправданы.

Итак, как мне создать единственный пул подключений и использовать его во всех файлах collections.js? Я хочу, чтобы такое соединение было реализовано в mongoose. Дайте мне знать, если какой-либо из моих мыслительных процессов в архитектуре приложения ошибочен.

Использование Mongoose решит эти проблемы, но я прочитал в нескольких местах, что он медленнее, чем родной драйвер, а также я бы предпочел модели без схемы.

Изменить: Я создал модуль из моделей. Каждая коллекция находилась в файле, и в качестве аргумента использовалась база данных. Теперь в файле index.js я вызвал соединение с базой данных и сохранил переменную db после того, как я получил базу данных из соединения. (Я использовал функцию автоматического повторного подключения, чтобы убедиться, что соединение не было потеряно). В том же файле index.js я экспортировал каждую из таких коллекций, как этот

exports.model1 = require('./model1').(db)
exprorts.model2 = require('./model2').(db)

Это обеспечило, чтобы часть базы данных обрабатывалась только одним модулем, и приложение просто вызывало функцию, которую экспортировал каждый файл model.js, например save(), fincdbyid() и т.д. (whatever you do in the function is upto you to implement).

Ответ 1

как подключиться к базе данных?

Чтобы подключиться с помощью встроенного драйвера MongoDB, вам нужно сделать что-то вроде следующего:

var util = require('util');
var mongodb = require('mongodb');
var client = mongodb.MongoClient;

var auth = {
    user: 'username',
    pass: 'password',
    host: 'hostname',
    port: 1337,
    name: 'databaseName'
};

var uri = util.format('mongodb://%s:%[email protected]%s:%d/%s',
    auth.user, auth.pass, auth.host, auth.port, auth.name);

/** Connect to the Mongo database at the URI using the client */
client.connect(uri, { auto_reconnect: true }, function (err, database) {
    if (err) throw err;
    else if (!database) console.log('Unknown error connecting to database');
    else {

        console.log('Connected to MongoDB database server at:');
        console.log('\n\t%s\n', uri);

        // Create or access collections, etc here using the database object
    }
});

Базовое соединение настроено так. Это все, что я могу дать вам, просто базовое описание того, что вы хотите. Опубликуйте код, который у вас есть, чтобы получить более конкретную помощь.

Должен ли я создать соединение в каждом из этих файлов и использовать их?

Нет.

Итак, как мне создать единственный пул подключений и использовать его во всех файлах collections.js?

Вы можете создать один файл с кодом, подобным приведенному выше, и позвоните ему dbmanager.js, соединяющемуся с базой данных. Экспортируйте функции, такие как createUser, deleteUser и т.д., Которые работают с вашей базой данных, а затем экспортируют такие функции:

module.exports = {
    createUser: function () { ; },
    deleteUser: function () { ; }
};

который вы могли бы затем require из другого файла:

var dbman = require('./dbmanager');

dbman.createUser(userData); // using connection established in `dbmanager.js`

EDIT:. Поскольку мы имеем дело с JavaScript и одним потоком, собственный драйвер действительно автоматически обрабатывает пул соединений. Вы можете найти это в ссылках StackOverflow ниже, чтобы получить больше подтверждения. ОП указывает это и в вопросе. Это означает, что client.connect следует вызывать только один экземпляр вашего сервера. После того, как объект database будет успешно извлечен из вызова client.connect, этот объект database должен быть повторно использован во всем экземпляре вашего приложения. Это легко осуществить, используя шаблон модуля, который Node.JS обеспечивает.

Мое предложение - создать модуль или набор модулей, которые служат одной точкой контакта для взаимодействия с базой данных. В моих приложениях у меня обычно есть один модуль, который зависит от собственного драйвера, вызывающего require('mongodb'). Все остальные модули в моем приложении не будут напрямую обращаться к базе данных, но вместо этого все манипуляции должны координироваться этим модулем базы данных.

Это инкапсулирует весь код, связанный с собственным драйвером, в один модуль или набор модулей. Кажется, что OP думает, что есть проблема с простым примером кода, который я опубликовал, описывая проблему с "одним большим закрытием" в моем примере. Это все довольно простые вещи, поэтому я добавляю разъяснения относительно базовой архитектуры здесь, но я все еще не чувствую необходимости изменять какой-либо код.

OP также, похоже, думает, что здесь можно сделать несколько соединений. Это невозможно с этой настройкой. Если вы создали модуль, как я предлагаю выше, то при первом вызове require('./dbmanager') он выполнит код в файле dbmanager.js и вернет объект module.exports. Объект экспорта кэшируется и также возвращается при каждом последующем вызове require('./dbmanager'), однако код в dbmanager.js будет выполнен только с первым require.

Если вы не хотите создавать такой модуль, то другим вариантом будет экспортировать только database, переданный на обратный вызов для client.connect, и использовать его непосредственно в разных местах вашего приложения. Однако я рекомендую против этого, независимо от проблем с OP.

Аналогичные, возможно дублирующие вопросы Stackoverflow, среди прочих:

Ответ 2

Как говорится в принятом ответе: вы должны создать только одно соединение для всех входящих запросов и повторно использовать его, но в ответе отсутствует решение, которое будет создавать и кэшировать соединение. Для этого я написал специальное промежуточное ПО - express-mongo-db. На первый взгляд эта задача тривиальна, и большинство людей используют такой код:

var db;
function createConnection(req, res, next) {
    if (db) { req.db = db; next(); }
    client.connect(uri, { auto_reconnect: true }, function (err, database) {
        req.db = db = databse;
        next();
    });
}

app.use(createConnection);

Но этот код приводит к утечке соединения, когда одновременно поступает несколько запросов, а db - undefined. express-mongo-db решить это, удерживая входящих клиентов и вызывая connect только один раз, когда требуется модуль (а не при поступлении первого запроса).

Надеюсь, вы сочтете это полезным.

Ответ 3

Я просто подумал, что добавлю свой собственный метод соединения MongoDB для других заинтересованных или имеющих проблемы с различными методами.

Этот метод предполагает, что вам не нужна аутентификация (я использую это на localhost)

Аутентификация по-прежнему легко реализовать

var MongoClient = require('mongodb').MongoClient;
var Server      = require('mongodb').Server;

var client = new MongoClient(new Server('localhost',27017,{
                                socketOptions: {connectTimeoutMS: 500},
                                poolSize:5,
                                auto_reconnect:true
                            }, {
                                numberOfRetries:3,
                                retryMilliseconds: 500
                            }));

client.open(function(err, client) {
    if(err) {
        console.log("Connection Failed Via Client Object.");
    } else {
        var db = client.db("theDbName");
        if(db) {
            console.log("Connected Via Client Object . . .");
            db.logout(function(err,result) {
                if(!err) {
                    console.log("Logged out successfully");
                }
                client.close();
                console.log("Connection closed");
            });
        }
    }
});

Кредит переходит к Брэду Дэви, который перебирает этот метод в своем book (стр. 231-232)