Подключение к 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).