node.js - true - url mongodb nodejs
¿Cómo administro las conexiones MongoDB en una aplicación web Node.js? (10)
Estoy usando el controlador node-mongodb-native con MongoDB para escribir un sitio web.
Tengo algunas preguntas sobre cómo gestionar las conexiones:
¿Es suficiente usar solo una conexión MongoDB para todas las solicitudes? ¿Hay problemas de rendimiento? Si no, ¿puedo configurar una conexión global para usar en toda la aplicación?
Si no es así, ¿es bueno si abro una nueva conexión cuando llega la solicitud y la cierro cuando se maneja la solicitud? ¿Es caro abrir y cerrar una conexión?
¿Debo usar un grupo de conexión global? He oído que el controlador tiene un grupo de conexión nativo. ¿Es una buena elección?
Si uso un grupo de conexiones, ¿cuántas conexiones se deben usar?
¿Hay otras cosas que debería notar?
Abra una nueva conexión cuando se inicie la aplicación Node.js y vuelva a usar el objeto de conexión db
existente:
/server.js
import express from ''express'';
import Promise from ''bluebird'';
import logger from ''winston'';
import { MongoClient } from ''mongodb'';
import config from ''./config'';
import usersRestApi from ''./api/users'';
const app = express();
app.use(''/api/users'', usersRestApi);
app.get(''/'', (req, res) => {
res.send(''Hello World'');
});
// Create a MongoDB connection pool and start the application
// after the database connection is ready
MongoClient.connect(config.database.url, { promiseLibrary: Promise }, (err, db) => {
if (err) {
logger.warn(`Failed to connect to the database. ${err.stack}`);
}
app.locals.db = db;
app.listen(config.port, () => {
logger.info(`Node.js app is listening at http://localhost:${config.port}`);
});
});
/api/users.js
import { Router } from ''express'';
import { ObjectID } from ''mongodb'';
const router = new Router();
router.get(''/:id'', async (req, res, next) => {
try {
const db = req.app.locals.db;
const id = new ObjectID(req.params.id);
const user = await db.collection(''user'').findOne({ _id: id }, {
email: 1,
firstName: 1,
lastName: 1
});
if (user) {
user.id = req.params.id;
res.send(user);
} else {
res.sendStatus(404);
}
} catch (err) {
next(err);
}
});
export default router;
Fuente: Cómo abrir conexiones de base de datos en una aplicación Node.js / Express
Aquí hay un código que administrará sus conexiones MongoDB.
var MongoClient = require(''mongodb'').MongoClient;
var url = require("../config.json")["MongoDBURL"]
var option = {
db:{
numberOfRetries : 5
},
server: {
auto_reconnect: true,
poolSize : 40,
socketOptions: {
connectTimeoutMS: 500
}
},
replSet: {},
mongos: {}
};
function MongoPool(){}
var p_db;
function initPool(cb){
MongoClient.connect(url, option, function(err, db) {
if (err) throw err;
p_db = db;
if(cb && typeof(cb) == ''function'')
cb(p_db);
});
return MongoPool;
}
MongoPool.initPool = initPool;
function getInstance(cb){
if(!p_db){
initPool(cb)
}
else{
if(cb && typeof(cb) == ''function'')
cb(p_db);
}
}
MongoPool.getInstance = getInstance;
module.exports = MongoPool;
Cuando inicie el servidor, llame a initPool
require("mongo-pool").initPool();
Luego en cualquier otro módulo puedes hacer lo siguiente:
var MongoPool = require("mongo-pool");
MongoPool.getInstance(function (db){
// Query your MongoDB database.
});
Esto se basa en la documentación de MongoDB . Mira esto.
Debe crear una conexión como servicio y luego reutilizarla cuando sea necesario.
// db.service.js
import { MongoClient } from "mongodb";
import database from "../config/database";
const dbService = {
db: undefined,
connect: callback => {
MongoClient.connect(database.uri, function(err, data) {
if (err) {
MongoClient.close();
callback(err);
}
dbService.db = data;
console.log("Connected to database");
callback(null);
});
}
};
export default dbService;
mi muestra de App.js
// App Start
dbService.connect(err => {
if (err) {
console.log("Error: ", err);
process.exit(1);
}
server.listen(config.port, () => {
console.log(`Api runnning at ${config.port}`);
});
});
y úsalo donde quieras con
import dbService from "db.service.js"
const db = dbService.db
El mejor enfoque para implementar la agrupación de conexiones es que debe crear una variable de matriz global que mantenga el nombre de la base de datos con el objeto de conexión devuelto por MongoClient y luego reutilizar esa conexión cada vez que necesite ponerse en contacto con la base de datos.
En su Server.js defina var global.dbconnections = [];
Crear un servicio nombrando connectionService.js. Tendrá 2 métodos getConnection y createConnection. Entonces, cuando el usuario llame a getConnection (), encontrará detalles en la variable de conexión global y devolverá los detalles de la conexión, si ya existe, llamará a createConnection () y devolverá los detalles de la conexión.
Llame a este servicio utilizando db_name y devolverá el objeto de conexión. Si ya tiene otra cosa, creará una nueva conexión y se la devolverá.
Espero eso ayude :)
Aquí está el código connectionService.js:
var mongo = require(''mongoskin'');
var mongodb = require(''mongodb'');
var Q = require(''q'');
var service = {};
service.getConnection = getConnection ;
module.exports = service;
function getConnection(appDB){
var deferred = Q.defer();
var connectionDetails=global.dbconnections.find(item=>item.appDB==appDB)
if(connectionDetails){deferred.resolve(connectionDetails.connection);
}else{createConnection(appDB).then(function(connectionDetails){
deferred.resolve(connectionDetails);})
}
return deferred.promise;
}
function createConnection(appDB){
var deferred = Q.defer();
mongodb.MongoClient.connect(connectionServer + appDB, (err,database)=>
{
if(err) deferred.reject(err.name + '': '' + err.message);
global.dbconnections.push({appDB: appDB, connection: database});
deferred.resolve(database);
})
return deferred.promise;
}
Gestione grupos de conexiones mongo en un único módulo autónomo. Este enfoque proporciona dos beneficios. En primer lugar, mantiene su código modular y más fácil de probar. En segundo lugar, no está obligado a mezclar su conexión de base de datos en su objeto de solicitud, que NO es el lugar para un objeto de conexión de base de datos. (Dada la naturaleza de JavaScript, consideraría altamente peligroso mezclar cualquier cosa con un objeto construido por el código de la biblioteca). Así que con eso solo necesitas considerar un módulo que exporte dos métodos. connect = () => Promise
and get = () => dbConnectionObject
.
Con un módulo así, primero puede conectarse a la base de datos
// runs in boot.js or what ever file your application starts with
const db = require(''./myAwesomeDbModule'');
db.connect()
.then(() => console.log(''database connected''))
.then(() => bootMyApplication())
.catch((e) => {
console.error(e);
// Always hard exit on a database connection error
process.exit(1);
});
Cuando está en vuelo, su aplicación puede simplemente llamar a get()
cuando necesita una conexión DB.
const db = require(''./myAwesomeDbModule'');
db.get().find(...)... // I have excluded code here to keep the example simple
Si configura su módulo db de la misma manera que la siguiente, no solo tendrá una manera de asegurarse de que su aplicación no se iniciará a menos que tenga una conexión de base de datos, también tiene una forma global de acceder a su grupo de conexiones de base de datos que dará error Si no tienes conexión.
// myAwesomeDbModule.js
let connection = null;
module.exports.connect = () => new Promise((resolve, reject) => {
MongoClient.connect(url, option, function(err, db) {
if (err) { reject(err); return; };
resolve(db);
connection = db;
});
});
module.exports.get = () => {
if(!connection) {
throw new Error(''Call connect first!'');
}
return connection;
}
He estado usando genérico-pool con conexiones redis en mi aplicación, lo recomiendo altamente. Es genérico y definitivamente sé que funciona con mysql, así que no creo que tengas ningún problema con él y Mongo.
He implementado el código a continuación en mi proyecto para implementar la agrupación de conexiones en mi código para que cree una conexión mínima en mi proyecto y reutilice la conexión disponible
/* Mongo.js*/
var MongoClient = require(''mongodb'').MongoClient;
var url = "mongodb://localhost:27017/yourdatabasename";
var assert = require(''assert'');
var connection=[];
// Create the database connection
establishConnection = function(callback){
MongoClient.connect(url, { poolSize: 10 },function(err, db) {
assert.equal(null, err);
connection = db
if(typeof callback === ''function'' && callback())
callback(connection)
}
)
}
function getconnection(){
return connection
}
module.exports = {
establishConnection:establishConnection,
getconnection:getconnection
}
/*app.js*/
// establish one connection with all other routes will use.
var db = require(''./routes/mongo'')
db.establishConnection();
//you can also call with callback if you wanna create any collection at starting
/*
db.establishConnection(function(conn){
conn.createCollection("collectionName", function(err, res) {
if (err) throw err;
console.log("Collection created!");
});
};
*/
// anyother route.js
var db = require(''./mongo'')
router.get(''/'', function(req, res, next) {
var connection = db.getconnection()
res.send("Hello");
});
Si tiene Express.js, puede usar github.com/floatdrop/express-mongo-db para almacenar en caché y compartir la conexión MongoDB entre solicitudes sin un grupo (ya que la respuesta aceptada dice que es la forma correcta de compartir la conexión).
Si no, puedes mirar su código fuente y usarlo en otro marco.
http://mongoosejs.com/docs/api.html
Echa un vistazo a la fuente de Mangosta. Abren una conexión y la vinculan a un objeto Modelo, de modo que cuando se requiere el Objeto modelo, se realiza una conexión a la base de datos. El conductor se encarga de la agrupación de conexiones.
El conmutador principal de node-mongodb-native dice :
Abre do MongoClient.connect una vez cuando su aplicación se inicia y reutiliza el objeto db. No es una agrupación de conexiones singleton cada .connect crea una nueva agrupación de conexiones.
Entonces, para responder directamente a su pregunta, reutilice el objeto db que resulta de MongoClient.connect (). Esto le permite agruparse y le proporcionará un notable aumento de velocidad en comparación con las conexiones de apertura / cierre en cada acción de db.