问一个Nodejs+mongodb的问题

问一个Nodejs+mongodb的问题

我用的数据库是Mongodb,然后连接的模块是是mongodb. package.json 里面配置的是,“mongodb”:"*" 我在根目录下建立了一个conDB.js的文件是想用来连接到mongodb数据库,具体代码如下: var mongodb = require(‘mongodb’); var server = new mongodb.Server(‘localhost’,27017,{auto_reconnect:true}); module.exports = server;

然后再一个user.js的文件: var server = require(’…/conDB’); var mongodb = require(‘mongodb’); var db = new mongodb.Db(‘user’,server,{safe:true});

exports.login=function (req,res,next) { db.open(function(err,db){ if(!err) {
db.collection(‘user’, function(err, collection){ collection.count({“username”:req.body.username,“pwd”:req.body.pwd},function(err,count){ if(count==1){ res.json(“ok”); } else{ res.json(“err”); } }) }); }else{ res.json(“err”); } }); };

当我第一次登陆以后一切正常,如果这个时候我改url ,到登陆页面的时候,我再一次输入账号密码来登陆系统,这个时候问题就出来了,提示错误信息是:Error: db object already connecting, open cannot be called multiple times 这个意思大概是说我已经有打开的链接了吧。我现在的问题是 第一:如果按我这个思路来做,应该怎么来处理这样的问题?我自己在conDB.js里面用过server.connected这个来查看链接状态 结果永远都是false. 第二:如果我的思路是错的,哪有没有其他正确的方法


6 回复

根据你的描述,你遇到了一个常见的问题:重复打开数据库连接导致的错误。为了解决这个问题,我们可以采用一些最佳实践,比如使用单例模式确保数据库连接只被打开一次,并且在整个应用程序中复用同一个连接。

解决方案

1. 单例模式连接 MongoDB

首先,我们修改 conDB.js 文件,使其成为一个单例模式,确保每次调用时返回相同的数据库连接实例。

// conDB.js
const MongoClient = require('mongodb').MongoClient;

let dbInstance = null;
let dbConnection = null;

const connectToDatabase = async () => {
    if (!dbInstance) {
        const uri = 'mongodb://localhost:27017';
        dbConnection = await MongoClient.connect(uri, { useNewUrlParser: true, useUnifiedTopology: true });
        dbInstance = dbConnection.db('user');
    }
    return dbInstance;
};

module.exports = connectToDatabase;

2. 使用连接实例

接下来,在 user.js 中使用这个单例模式来获取数据库连接实例。

// user.js
const connectToDatabase = require('./conDB');

exports.login = async function (req, res, next) {
    try {
        const db = await connectToDatabase();
        const count = await db.collection('users').countDocuments({
            username: req.body.username,
            pwd: req.body.pwd
        });

        if (count === 1) {
            res.json("ok");
        } else {
            res.json("err");
        }
    } catch (error) {
        console.error(error);
        res.json("err");
    }
};

解释

  • 单例模式:通过在 conDB.js 中使用单例模式,我们确保了数据库连接只会被打开一次,并且可以在整个应用中复用。
  • 异步操作:使用 async/await 来处理异步操作,使代码更简洁易读。
  • 错误处理:增加了错误处理逻辑,以确保在出现错误时能够妥善处理并返回适当的响应。

这样,你就可以避免重复打开数据库连接的问题,并且代码也更加健壮和易于维护。


  1. 把数据库常连接放在接口 function login (req, res, connect) {...} 或者
    function login (connect) {
        return function (req, res) {...}
    }
  1. 把数据库模块设为单例,并在第一次require的时候,初始化配置 该文件可以这样写:
    var connect = ... 你的连接
function a () { connect... }
function b () { connect... }
 ...

so, 当require该文件,通过cache只需要一次连接。

我自己搞定了,就加了一个判断代码如下: exports.login=function (req,res,next) { if(server._serverState==“connected”) { db.close(); } db.open(function(err,db){ if(!err) {
db.collection(‘user’, function(err, collection){ collection.count({“username”:req.body.username,“pwd”:req.body.pwd},function(err,count){ if(count==1){ res.json(“ok”); return; } else{ res.json(“err”); } }) }); }else{ db.close(); res.json(“err”); } }); }; 在db.open 之前判断一下。 虽然问题解决了,但是总感觉这样写不对劲,还请各位 写过这方面代码的同学贴点代码出来

不必要每次开,每次关。 一直连接着就好了。

//读取用户信息 User.get = function(name, callback) { //打开数据库 mongodb.open(function (err, db) { if (err) { return callback(err);//错误,返回 err 信息 } //读取 users 集合 db.collection(‘users’, function (err, collection) { if (err) { mongodb.close(); return callback(err);//错误,返回 err 信息 } //查找用户名(name键)值为 name 一个文档 collection.findOne({ name: name }, function (err, user) { mongodb.close(); if (err) { return callback(err);//失败!返回 err 信息 } callback(null, user);//成功!返回查询的用户信息 }); }); }); }; 这是我的用户的一个方法,呵呵, 我的一个简单的博客,求支持下,谢啦 http://blog.gaoqixhb.com

根据你的描述,你遇到的问题是因为在conDB.js中只创建了一个MongoDB服务器实例,并且在user.js中的每次请求都尝试重新打开数据库连接,这会导致重复连接的问题。

解决方案

  1. 使用MongoDB驱动的内置功能
    • 使用MongoClient而不是手动管理连接。
    • MongoClient可以自动处理连接池和重连逻辑。

示例代码

conDB.js

const { MongoClient } = require('mongodb');

// 创建一个MongoClient实例
const uri = 'mongodb://localhost:27017';
const dbName = 'your_database_name';

let dbInstance;

const connectToDb = async () => {
  const client = new MongoClient(uri, { useNewUrlParser: true, useUnifiedTopology: true });

  try {
    await client.connect();
    console.log('Connected to MongoDB');
    dbInstance = client.db(dbName);
  } catch (error) {
    console.error('Failed to connect to MongoDB', error);
  }

  return dbInstance;
};

module.exports = {
  getDb: () => dbInstance || connectToDb(),
};

user.js

const express = require('express');
const router = express.Router();
const { getDb } = require('./conDB');

router.post('/login', async (req, res, next) => {
  try {
    const db = await getDb();
    const count = await db.collection('user').countDocuments({
      username: req.body.username,
      pwd: req.body.pwd
    });

    if (count === 1) {
      res.json("ok");
    } else {
      res.json("err");
    }
  } catch (error) {
    console.error('Error during login', error);
    res.status(500).json("err");
  }
});

module.exports = router;

解释

  • conDB.js:创建一个MongoClient实例,并将其存储在一个变量中。当需要访问数据库时,使用getDb函数来获取当前的数据库连接。如果尚未连接,则会先连接。
  • user.js:使用getDb函数来获取数据库连接,避免重复连接的问题。这里还使用了countDocuments方法,它更简洁且推荐用于查询文档数量。

这样处理可以确保每个请求都能正确地访问数据库,而不会出现重复连接的问题。

回到顶部