Node.js和MongoDB,重复使用DB对象

17

我对Node.js和MongoDB都很新,但我已经从SO和mongo的文档中组合了一些部分。

mongo文档中给出了示例:

// Retrieve
var MongoClient = require('mongodb').MongoClient;

// Connect to the db
MongoClient.connect("mongodb://localhost:27017/exampleDb", function(err, db) {
  if(!err) {
    console.log("We are connected");
  }
});

如果我只需要在一个函数的一个地方使用数据库,那么这看起来很好。在SO上搜索和阅读后,我发现每次不应该打开新连接,而是应该使用池并重复使用第一次获得的数据库对象。这个答案在SO上非常丰富,但我不确定如何首先获取DB对象,然后如何重用它。

假设我在我的App.js中有上面的Node.js代码,然后我有不同的路由需要对数据库运行不同的操作:

app.post('/employee', function(req, res){
    //Put req.name in database
});


app.post('/car', function(req, res){
    //Put req.car in database
});

我该如何将这两个片段组合成有用的东西?

我在Node.js重用MongoDB引用中找到了一个类似的问题,但从这个(http://mongodb.github.io/node-mongodb-native/driver-articles/mongoclient.html)的样子来看,我应该使用MongoClient而不是db()。而且我也不确定它是否解决了我的问题...

2个回答

37

你可以编写一个模块来初始化数据库连接,并使其在整个程序中可访问。例如:

mongo.js

var mongodb = require('mongodb');

module.exports.init = function (callback) {
  var server = new mongodb.Server("127.0.0.1", 27017, {});
  new mongodb.Db('test', server, {w: 1}).open(function (error, client) {
    //export the client and maybe some collections as a shortcut
    module.exports.client = client;
    module.exports.myCollection = new mongodb.Collection(client, 'myCollection');
    callback(error);
  });
};

app.js

var mongo = require('./mongo.js');

//setup express...

//initialize the db connection
mongo.init(function (error) {
    if (error)
        throw error;

    app.listen(80); //database is initialized, ready to listen for connections
});

随机文件.js

var mongo = require('./mongo.js');

module.exports.doInsert = function () {
  //use the collection object exported by mongo.js
  mongo.myCollection.insert({test: 'obj'}, {safe:true}, function(err, objects) {
    if (err)
        console.warn(err.message);
  });
};

我知道人们谈论连接池,但当我对比池化Mongo连接和单一连接处理所有请求时,单一连接实际上表现更好。当然,这是大约一年前的事情,但我怀疑基本概念是否已改变。所有的请求都是异步的,因此并不需要多个连接以便进行同时请求。

就 MongoClient 而言,我想这是他们鼓励使用的新语法。无论哪种方式,它本质上都是一个客户端对象,您希望保留并使其在使用任何样式时都可以访问。


嗯,在尝试之前,我得先研究一下模块和相关内容。"module.exports.init" 看起来很奇怪 :) 但你的意思是说 "app.js" 中的代码只需要运行一次,然后在 "randomFile.js" 中的代码就可以在我的 app.post('/employee') 中使用了?作为第一次尝试,我把所有东西都放在一个 App.js 文件中。 - user2288749
没错,init函数应该只被调用一次。randomFile.js只是一个示例,展示了你可以在代码的任何地方使用已初始化的数据库。它同样可以在app.js中轻松使用。如果你要使用Node进行开发,你一定要理解模块是如何工作的,但它们并不难。 - Bret Copeland
我不确定你为什么认为有五个连接。它应该只有一个。 - Bret Copeland
这是使用本地Node MongoDB驱动程序管理数据库连接的单一完美答案,但在谷歌上却很难找到。 - Serhat Ozgel
3
看起来 MongoDB 驱动程序会自动执行一些连接池操作,这就是为什么有 5 个连接的原因。MongoClient.connect() 所做的是创建一个连接池。 - Serhat Ozgel
显示剩余8条评论

3
根据你之前的代码片段,看起来你正在使用Express或类似的框架。你可以使用express-mongo-dbreq对象中获取连接。这个中间件会为你缓存连接,并与其他进入的请求共享它:
app.use(require('express-mongo-db')(require('mongodb'), { db: 'test' }))
app.post('/employee', function(req, res){
    // req.db.collection('names'),insert(req.name)
    // Put req.name in database
});


app.post('/car', function(req, res){
    // req.db.collection('names').insert(req.name)
    // Put req.car in database
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接