我在express.js应用程序中使用mongodb-本机驱动程序。我在数据库中有大约6个集合,所以我创建了6个js文件,每个文件都有一个作为javascript对象(例如function collection(){}
)的集合,以及处理这些集合上所有操作的原型函数。我觉得这是个很好的建筑。
但是我遇到的问题是如何连接到数据库?我应该在每个文件中创建一个连接并使用它们吗?,我认为这将是过度的,因为mongodb中的连接本机驱动程序创建了一个连接池,其中有几个是不合理的。
,那么我如何创建一个连接池,并在所有的collections.js文件中使用它呢?,我想让连接像它在猫鼬中实现的那样。让我知道,如果我的思维过程在架构的应用程序是错误的。
使用Mongoose可以解决这些问题,但是我在几个地方读过,它比本地驱动程序慢,而且我更喜欢没有模式的模型。
编辑:我用模型创建了一个模块。每个集合都在一个文件中,它将数据库作为参数。现在,在index.js文件中,我调用了数据库连接,并在从连接中获得数据库后保留了一个变量db。(我使用了自动重新连接功能,以确保连接没有丢失)。在同一个index.js文件中,我导出了如下所示的每个集合
exports.model1 = require('./model1').(db)
exprorts.model2 = require('./model2').(db)
这确保了数据库部分仅在一个模块中处理,应用程序只调用每个model.js文件导出的函数,如save()
、fincdbyid()
等(whatever you do in the function is upto you to implement
)。
发布于 2013-08-04 13:39:13
如何连接到数据库?
为了使用MongoDB本机驱动程序进行连接,需要执行以下操作:
var util = require('util');
var mongodb = require('mongodb');
var client = mongodb.MongoClient;
var auth = {
user: 'username',
pass: 'password',
host: 'hostname',
port: 1337,
name: 'databaseName'
};
var uri = util.format('mongodb://%s:%s@%s:%d/%s',
auth.user, auth.pass, auth.host, auth.port, auth.name);
/** Connect to the Mongo database at the URI using the client */
client.connect(uri, { auto_reconnect: true }, function (err, database) {
if (err) throw err;
else if (!database) console.log('Unknown error connecting to database');
else {
console.log('Connected to MongoDB database server at:');
console.log('\n\t%s\n', uri);
// Create or access collections, etc here using the database object
}
});
一个基本的连接是这样设置的。这就是我所能给你的只是你想要的东西的基本描述。张贴一些代码,您到目前为止,以获得更具体的帮助。
我应该在每个文件中创建一个连接并使用它们吗?
不是的。
,那么我如何创建一个连接池并在所有的collections.js文件中使用它呢?
您可以使用上面的代码创建一个文件,让我们称它为dbmanager.js
连接到数据库。在数据库上运行的导出函数(如createUser
、deleteUser
等),然后导出功能如下:
module.exports = {
createUser: function () { ; },
deleteUser: function () { ; }
};
然后,您可以从另一个文件进行require
,如下所示:
var dbman = require('./dbmanager');
dbman.createUser(userData); // using connection established in `dbmanager.js`
编辑:,因为我们处理的是JavaScript和单个线程,本机驱动程序实际上会自动为您处理连接池。您可以在下面的StackOverflow链接中查找这一点,以获得更多的确认。“任择议定书”也在问题中说明了这一点。这意味着client.connect
只应该被服务器的一个实例调用一次。在成功地从对database
的调用中检索到client.connect
对象之后,应该在应用程序的整个实例中重用该database
对象。这很容易通过使用Node.JS提供的模块模式来实现。
我的建议是创建一个或多个模块集,作为与数据库交互的单一接触点。在我的应用程序中,我通常有一个依赖于本地驱动程序的模块,即调用require('mongodb')
。我的应用程序中的所有其他模块都不会直接访问数据库,而是所有操作都必须由这个数据库模块协调。
这将处理本机驱动程序的所有代码封装到一个或多个模块中。OP似乎认为我发布的简单代码示例存在问题,在我的示例中描述了“单个大闭包”的问题。这都是非常基本的东西,所以我在这里添加对基本架构的澄清,但我仍然不觉得有必要修改任何代码。
OP似乎还认为在这里可以建立多个连接。这种设置是不可能的。如果像我前面建议的那样创建了一个模块,那么第一次调用require('./dbmanager')
时,它将执行文件dbmanager.js
中的代码并返回module.exports
对象。导出对象被缓存,并在每次调用require('./dbmanager')
时返回,但是,dbmanager.js
中的代码将只执行第一个require
。
如果您不想创建这样的模块,那么另一种选择是只导出传递给client.connect
回调的client.connect
,并在整个应用程序的不同位置直接使用它。然而,我建议不要这样做,不管OPs有什么顾虑。
类似的、可能重复的堆栈溢出问题,除其他外:
发布于 2014-08-08 10:43:00
正如公认的答案所述-您应该只为所有传入请求创建一个连接并重用它,但是答案是缺少的解决方案,这将创建和缓存连接。我编写了快速中间件来实现这一目标-- 特快专递。乍一看,这个任务是微不足道的,大多数人使用这种代码:
var db;
function createConnection(req, res, next) {
if (db) { req.db = db; next(); }
client.connect(uri, { auto_reconnect: true }, function (err, database) {
req.db = db = databse;
next();
});
}
app.use(createConnection);
但是,当多个请求同时到达时,当db
未定义时,此代码将导致连接泄漏。express-mongo-db
通过保持传入客户端并只在需要模块时(而不是在第一个请求到达时)调用connect
一次来解决这个问题。
希望你觉得有用。
发布于 2014-08-20 17:52:28
我只是想为其他感兴趣或有问题的人添加我自己的MongoDB连接方法
此方法假定您不需要身份验证(我在本地主机上使用此方法)
身份验证仍然容易实现。
var MongoClient = require('mongodb').MongoClient;
var Server = require('mongodb').Server;
var client = new MongoClient(new Server('localhost',27017,{
socketOptions: {connectTimeoutMS: 500},
poolSize:5,
auto_reconnect:true
}, {
numberOfRetries:3,
retryMilliseconds: 500
}));
client.open(function(err, client) {
if(err) {
console.log("Connection Failed Via Client Object.");
} else {
var db = client.db("theDbName");
if(db) {
console.log("Connected Via Client Object . . .");
db.logout(function(err,result) {
if(!err) {
console.log("Logged out successfully");
}
client.close();
console.log("Connection closed");
});
}
}
});
归功于布拉德达维,他在他的书 (第231-232页)中对这种方法进行了研究。
https://stackoverflow.com/questions/18044113
复制