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

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

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

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

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

Изменить: я создал модуль из моделей. Каждая коллекция была в файле, и в качестве аргумента использовалась база данных. Теперь в файле 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).

3 ответа

Решение

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

Чтобы подключиться с помощью собственного драйвера 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:%s@%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
    }
});

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

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

Нет.

Итак, как мне создать единый пул соединений и использовать его во всех файлах collection.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`

РЕДАКТИРОВАТЬ: Поскольку мы имеем дело с JavaScript и одним потоком, нативный драйвер действительно автоматически обрабатывает пул соединений для вас. Вы можете найти это в ссылках Stackru ниже для большего подтверждения этого. ФП также заявляет об этом в вопросе. Это означает, что client.connect должен вызываться только один раз экземпляром вашего сервера. После database объект успешно извлечен из вызова client.connect, тот database объект должен быть повторно использован во всем экземпляре вашего приложения. Это легко сделать с помощью шаблона модуля, который предоставляет Node.JS.

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

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

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

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

Подобные, возможно, дублирующие вопросы Stackru, среди прочего:

Как говорится в принятом ответе - вы должны создать только одно соединение для всех входящих запросов и использовать его повторно, но в ответе отсутствует решение, которое создаст и кеширует соединение. Я написал Express Middleware для достижения этой цели - 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 не определено express-mongo-db решить эту проблему путем удержания входящих клиентов и вызова connect только один раз, когда требуется модуль (не при поступлении первого запроса).

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

Я просто подумал, что добавлю свой метод подключения 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");
            });
        }
    }
});

Благодарность принадлежит Брэду Дэвли, который описывает этот метод в своей книге (стр. 231-232).

Другие вопросы по тегам