如何在 Node.js Web 应用程序中管理 MongoDB 连接?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10656574/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I manage MongoDB connections in a Node.js web application?
提问by Freewind
I'm using the node-mongodb-nativedriver with MongoDB to write a website.
我正在使用带有 MongoDB的node-mongodb-native驱动程序来编写网站。
I have some questions about how to manage connections:
我有一些关于如何管理连接的问题:
Is it enough using only one MongoDB connection for all requests? Are there any performance issues? If not, can I setup a global connection to use in the whole application?
If not, is it good if I open a new connection when request arrives, and close it when handled the request? Is it expensive to open and close a connection?
Should I use a global connection pool? I hear the driver has a native connection pool. Is it a good choice?
If I use a connection pool, how many connections should be used?
Are there other things I should notice?
仅对所有请求使用一个 MongoDB 连接就足够了吗?是否有任何性能问题?如果没有,我可以设置一个全局连接以在整个应用程序中使用吗?
如果没有,如果我在请求到达时打开一个新连接并在处理请求时关闭它是否很好?打开和关闭连接是否昂贵?
我应该使用全局连接池吗?我听说驱动程序有一个本机连接池。这是一个不错的选择吗?
如果我使用连接池,应该使用多少个连接?
还有其他我应该注意的事情吗?
回答by Max
The primary committer to node-mongodb-native says:
You open do MongoClient.connect once when your app boots up and reuse the db object. It's not a singleton connection pool each .connect creates a new connection pool.
当您的应用程序启动并重用 db 对象时,您打开 do MongoClient.connect 一次。它不是一个单独的连接池,每个 .connect 都会创建一个新的连接池。
So, to answer your question directly, reuse the db object that results from MongoClient.connect(). This gives you pooling, and will provide a noticeable speed increase as compared with opening/closing connections on each db action.
因此,要直接回答您的问题,请重用由MongoClient.connect(). 这为您提供了池化,并且与在每个 db 操作上打开/关闭连接相比,将显着提高速度。
回答by Konstantin Tarkus
Open a new connection when the Node.js application starts, and reuse the existing dbconnection object:
在 Node.js 应用程序启动时打开一个新连接,并重用现有的db连接对象:
/server.js
/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
/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;
Source: How to Open Database Connections in a Node.js/Express App
来源:如何在 Node.js/Express 应用程序中打开数据库连接
回答by Yaki Klein
Here is some code that will manage your MongoDB connections.
下面是一些将管理您的 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;
When you start the server, call initPool
当你启动服务器时,调用 initPool
require("mongo-pool").initPool();
Then in any other module you can do the following:
然后在任何其他模块中,您可以执行以下操作:
var MongoPool = require("mongo-pool");
MongoPool.getInstance(function (db){
// Query your MongoDB database.
});
This is based on MongoDB documentation. Take a look at it.
这是基于MongoDB 文档。看一看。
回答by Stewart
Manage mongo connection pools in a single self contained module. This approach provides two benefits. Firstly it keeps your code modular and easier to test. Secondly your not forced to mix your database connection up in your request object which is NOT the place for a database connection object. (Given the nature of JavaScript I would consider it highly dangerous to mix in anything to an object constructed by library code). So with that you only need to Consider a module that exports two methods. connect = () => Promiseand get = () => dbConnectionObject.
在单个自包含模块中管理 mongo 连接池。这种方法有两个好处。首先,它使您的代码保持模块化并且更易于测试。其次,您不必在请求对象中混合数据库连接,这不是数据库连接对象的位置。(鉴于 JavaScript 的性质,我认为将任何内容混合到由库代码构造的对象中是非常危险的)。因此,您只需要考虑一个导出两种方法的模块。connect = () => Promise和get = () => dbConnectionObject。
With such a module you can firstly connect to the database
使用这样的模块,您可以首先连接到数据库
// 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);
});
When in flight your app can simply call get()when it needs a DB connection.
在飞行中,您的应用程序可以get()在需要数据库连接时简单地调用。
const db = require('./myAwesomeDbModule');
db.get().find(...)... // I have excluded code here to keep the example simple
If you set up your db module in the same way as the following not only will you have a way to ensure that your application will not boot unless you have a database connection you also have a global way of accessing your database connection pool that will error if you have not got a connection.
如果您以与以下相同的方式设置 db 模块,您不仅可以确保除非您有数据库连接,否则您的应用程序不会启动,您还可以通过全局方式访问会出错的数据库连接池如果您还没有建立连接。
// 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;
}
回答by floatdrop
If you have Express.js, you can use express-mongo-dbfor caching and sharing the MongoDB connection between requests without a pool (since the accepted answer says it is the right way to share the connection).
如果你有 Express.js,你可以使用express-mongo-db在没有池的请求之间缓存和共享 MongoDB 连接(因为接受的答案说这是共享连接的正确方法)。
If not - you can look at its source code and use it in another framework.
如果没有 - 您可以查看其源代码并在另一个框架中使用它。
回答by ControlAltDel
I have been using generic-pool with redis connections in my app - I highly recommend it. Its generic and I definitely know it works with mysql so I don't think you'll have any problems with it and mongo
我一直在我的应用程序中使用带有 redis 连接的通用池 - 我强烈推荐它。它是通用的,我绝对知道它适用于 mysql,所以我认为你不会对它和 mongo 有任何问题
回答by srquinn
http://mongoosejs.com/docs/api.html
http://mongoosejs.com/docs/api.html
Check out the source of Mongoose. They open a connection and bind it to a Model object so when the model Object is required, a connection is made to the DB. The driver takes care of connection pooling.
查看猫鼬的来源。他们打开一个连接并将它绑定到一个模型对象,这样当需要模型对象时,就会建立到数据库的连接。驱动程序负责连接池。
回答by TheAlemazing
You should create a connection as service then reuse it when need.
您应该创建一个连接作为服务,然后在需要时重用它。
// 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;
my App.js sample
我的 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}`);
});
});
and use it wherever you want with
并随心所欲地使用它
import dbService from "db.service.js"
const db = dbService.db
回答by Aditya Parmar
I have implemented below code in my project to implement connection pooling in my code so it will create a minimum connection in my project and reuse available connection
我在我的项目中实现了以下代码以在我的代码中实现连接池,因此它将在我的项目中创建最小连接并重用可用连接
/* 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");
});
回答by RRPatel
Best approach to implement connection pooling is you should create one global array variable which hold db name with connection object returned by MongoClient and then reuse that connection whenever you need to contact Database.
实现连接池的最佳方法是创建一个全局数组变量,该变量保存数据库名称和 MongoClient 返回的连接对象,然后在需要联系数据库时重用该连接。
In your Server.js define var global.dbconnections = [];
Create a Service naming connectionService.js. It will have 2 methods getConnection and createConnection. So when user will call getConnection(), it will find detail in global connection variable and return connection details if already exists else it will call createConnection() and return connection Details.
Call this service using db_name and it will return connection object if it already have else it will create new connection and return it to you.
在你的 Server.js 中定义 var global.dbconnections = [];
创建一个名为 connectionService.js 的服务。它将有 2 个方法 getConnection 和 createConnection。因此,当用户调用 getConnection() 时,它将在全局连接变量中查找详细信息,如果已存在则返回连接详细信息,否则它将调用 createConnection() 并返回连接详细信息。
使用 db_name 调用此服务,如果它已经有连接对象,它将返回连接对象,否则它将创建新连接并将其返回给您。
Hope it helps :)
希望能帮助到你 :)
Here is the connectionService.js code:
这是 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;
}

