Nodejs mongodb连接数

Nodejs mongodb连接数

我写了一个网页,很简单。两张静态图片和一段存储在Mongodb中的文字。但是在不断刷新网页时会出现下面的错误: Error: db object already connecting, open cannot be called multiple times at Db.open (X:\BYSJ\Project\simulat\node_modules\mongodb\lib\mongodb\db.js:224:11) at exports.index (X:\BYSJ\Project\simulat\routes\index.js:16:12) at callbacks (X:\BYSJ\Project\simulat\node_modules\express\lib\router\index.js:161:37) at param (X:\BYSJ\Project\simulat\node_modules\express\lib\router\index.js:135:11) at pass (X:\BYSJ\Project\simulat\node_modules\express\lib\router\index.js:142:5) at Router._dispatch (X:\BYSJ\Project\simulat\node_modules\express\lib\router\index.js:170:5) at Object.router (X:\BYSJ\Project\simulat\node_modules\express\lib\router\index.js:33:10) at next (X:\BYSJ\Project\simulat\node_modules\express\node_modules\connect\lib\proto.js:190:15) at Object.methodOverride [as handle] (X:\BYSJ\Project\simulat\node_modules\express\node_modules\connect\lib\middleware\methodOverride.js:37:5) at next (X:\BYSJ\Project\simulat\node_modules\express\node_modules\connect\lib\proto.js:190:15)

我的代码如下: exports.index = function(req, res){ // var dbtest=require(‘dbcon’); var mongodb=require(‘mongodb’) , mongoserver=new mongodb.Server(‘localhost’,27017) ,dbtest=new mongodb.Db(‘test’,mongoserver,{w:-1});

// console.log(dbtest.serverConfig);
 var pas;
dbtest.open(function(err,db){
    if(err){
       // console.log(db)
        console.log("OPen Db Failed");
        //db.close();
        return res.redirect("/error");
    } else{
      db.collection('test',function(err,coll){
          if(err){
              console.log("Slect Collection  Failed");
              db.close();
              return res.redirect("/error");
          }
        coll.find({title:"test"}).toArray(function(err,doc){
            if(err){
                console.log("query data Failed");
                db.close();
                return   res.redirect("/error")   ;
            }
            pas=doc[0].con;
            //console.log(doc);
            res.locals.pas=pas;
            db.close();
           res.render('index', { title: 'Express' });
        })
      });
    }

});

};

请问问题出在哪啊?


11 回复

根据你提供的错误信息和代码片段,问题出在你多次尝试打开同一个数据库连接。在Node.js中,数据库连接应该只被创建和打开一次,并且可以在应用的不同部分复用。

解决方案

  1. 使用连接池:MongoDB Node.js驱动程序支持连接池,可以避免频繁地打开和关闭数据库连接。你可以通过配置MongoClient来使用连接池。

  2. 全局管理连接:将数据库连接逻辑放在一个全局可访问的地方(如app.js或单独的模块),以确保在整个应用生命周期中只打开一次连接。

示例代码

使用MongoClient连接池

首先安装mongodb库(如果尚未安装):

npm install mongodb

然后修改你的代码:

const MongoClient = require('mongodb').MongoClient;

let db;

async function connectToDatabase() {
    const client = new MongoClient('mongodb://localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true });
    await client.connect();
    console.log("Connected to MongoDB");
    db = client.db('test');
}

// 在应用启动时调用此函数
connectToDatabase().catch(console.error);

exports.index = async function(req, res) {
    try {
        const collection = db.collection('test');
        const doc = await collection.findOne({ title: "test" });
        if (!doc) {
            return res.redirect("/error");
        }
        res.locals.pas = doc.con;
        res.render('index', { title: 'Express' });
    } catch (err) {
        console.error("Failed to query data", err);
        res.redirect("/error");
    }
};

解释

  • 使用MongoClient:MongoClient是推荐的方式,它提供了更简洁的API和更好的性能。
  • 全局变量:我们将数据库对象存储在一个全局变量db中,以便在整个应用中复用。
  • 异步函数:我们使用async/await语法来处理异步操作,使代码更易读。

通过这种方式,你只需在应用启动时连接一次数据库,并在整个应用生命周期中复用该连接。这样可以避免多次打开同一连接的问题。


没有必要关闭 db,db 打开后保留给下次用。

db.close()

不关闭的话,持续打开不会造成系统资源耗尽吗?

打开一次,多次使用

不是打开多次。

我已开始也这么想过,但是我发现,如果不通过open函数打开数据库,无法获得db对象啊,因为err和db对象是作为参数传给回调函数的啊?

我看好象mongodb连接有超时的, 过一段时间mongodb会自动关闭的吧

你说的是连接池吗?

http://cnodejs.org/topic/51904ff263e9f8a5429fde30

你这个问题貌似论坛里面很早就有几个相关的,我暂时找到一个。

跟你问题比较相近的,应该是并发导致的

http://cnodejs.org/topic/51aacd56555d34c6785805eb

呵呵,谢谢,这个帖子也是我提问的,就是最近做毕业设计遇到各种问题。帖子里边推荐用mongoose和mongoskin,但是我也不知道时候能解决并发的问题。

根据你的描述,错误信息 Error: db object already connecting, open cannot be called multiple times 表明你在尝试多次打开同一个数据库连接。为了避免这个问题,你应该确保只创建一个数据库连接,并在整个应用程序中重用它。

你可以使用 MongoDB 的官方驱动程序中的 MongoClient 来管理连接池,这将自动处理连接的复用和关闭。下面是修改后的代码示例:

const MongoClient = require('mongodb').MongoClient;

let db;

MongoClient.connect('mongodb://localhost:27017/test', { useNewUrlParser: true, useUnifiedTopology: true }, (err, client) => {
  if (err) {
    console.log("Open DB Failed");
    return res.redirect('/error');
  }
  console.log("DB Connected!");
  db = client.db('test'); // 将数据库对象存储在一个全局变量中
});

exports.index = function(req, res) {
  if (!db) {
    console.log("DB not connected yet, please wait...");
    return res.redirect('/error');
  }

  db.collection('test').find({ title: "test" }).toArray((err, doc) => {
    if (err) {
      console.log("Query Data Failed");
      return res.redirect('/error');
    }
    res.locals.pas = doc[0].con;
    res.render('index', { title: 'Express' });
  });
};

解释

  • 使用 MongoClient: 使用 MongoClient 可以简化连接管理,并且支持连接池。
  • 全局变量存储数据库对象: 通过将数据库对象存储在全局变量 db 中,可以在不同的请求之间重用该连接。
  • 确保连接已建立: 在 index 方法中检查 db 是否已经连接,如果未连接,则返回错误页面。

这样可以避免多次调用 db.open() 导致的连接错误。

回到顶部