问一个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. 第二:如果我的思路是错的,哪有没有其他正确的方法
根据你的描述,你遇到了一个常见的问题:重复打开数据库连接导致的错误。为了解决这个问题,我们可以采用一些最佳实践,比如使用单例模式确保数据库连接只被打开一次,并且在整个应用程序中复用同一个连接。
解决方案
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
来处理异步操作,使代码更简洁易读。 - 错误处理:增加了错误处理逻辑,以确保在出现错误时能够妥善处理并返回适当的响应。
这样,你就可以避免重复打开数据库连接的问题,并且代码也更加健壮和易于维护。
- 把数据库常连接放在接口
function login (req, res, connect) {...}
或者
function login (connect) {
return function (req, res) {...}
}
- 把数据库模块设为单例,并在第一次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
中的每次请求都尝试重新打开数据库连接,这会导致重复连接的问题。
解决方案
- 使用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
方法,它更简洁且推荐用于查询文档数量。
这样处理可以确保每个请求都能正确地访问数据库,而不会出现重复连接的问题。