在 express.js 中连接到 Mongodb-Native-Driver
Posted
技术标签:
【中文标题】在 express.js 中连接到 Mongodb-Native-Driver【英文标题】:Connection to Mongodb-Native-Driver in express.js 【发布时间】:2013-08-05 07:56:24 【问题描述】:我在 express.js 应用程序中使用 mongodb-native-driver。我在数据库中有大约 6 个集合,所以我创建了 6 个 js 文件,每个文件都有一个作为 javascript 对象的集合(例如function collection()
),并且原型函数处理对这些集合的所有操作。我认为这将是一个很好的架构。
但我遇到的问题是如何连接到数据库?我应该在每个文件中创建一个连接并使用它们吗?我认为这将是一种矫枉过正,因为 mongodb-native-driver 中的连接会创建一个连接池并且拥有其中的几个是不合理的。
那么如何创建单个连接池并在所有 collections.js 文件中使用它?我希望像在 mongoose 中那样实现连接。如果我在应用程序架构中的任何思考过程是错误的,请告诉我。
使用 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
)。
【问题讨论】:
【参考方案1】:我只是想我会添加自己的 MongoDB 连接方法,以供其他感兴趣或遇到不同方法问题的人使用
此方法假定您不需要身份验证(我在 localhost 上使用此方法)
身份验证仍然很容易实现
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");
);
);
归功于 Brad Davley,他在他的 book(第 231-232 页)中介绍了这种方法
【讨论】:
【参考方案2】:正如接受的答案所说 - 您应该为所有传入请求只创建一个连接并重用它,但答案缺少解决方案,它将创建和缓存连接。我编写了 express 中间件来实现这一点 - express-mongo-db。乍一看,这个任务是微不足道的,大多数人都使用这种代码:
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
来解决此问题。
希望你觉得它有用。
【讨论】:
【参考方案3】:如何连接数据库?
为了使用 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 和单线程,所以本机驱动程序确实会自动为您处理连接池。您可以在下面的 *** 链接中查找此内容以获得更多确认。 OP也确实在问题中说明了这一点。这意味着client.connect
应该由您的服务器实例调用一次。在从对client.connect
的调用中成功检索到database
对象后,应在整个应用程序实例中重用该database
对象。这可以通过使用 Node.JS 提供的模块模式轻松实现。
我的建议是创建一个模块或一组模块,作为与数据库交互的单点联系。在我的应用程序中,我通常有一个依赖于本机驱动程序的模块,调用 require('mongodb')
。我的应用程序中的所有其他模块都不会直接访问数据库,而是所有操作都必须由该数据库模块协调。
这会将处理本机驱动程序的所有代码封装到单个模块或一组模块中。 OP 似乎认为我发布的简单代码示例存在问题,在我的示例中描述了“单个大闭包”的问题。这些都是非常基本的东西,所以我在这里添加了关于工作中的基本架构的说明,但我仍然觉得没有必要更改任何代码。
OP 似乎也认为可以在这里建立多个连接。使用此设置是不可能的。如果您创建了我上面建议的模块,那么第一次调用require('./dbmanager')
时,它将执行文件dbmanager.js
中的代码并且 返回module.exports
对象。导出对象被缓存,并且在每次后续调用require('./dbmanager')
时也会返回,但是dbmanager.js
中的代码只会在第一个require
中执行。
如果您不想创建这样的模块,那么另一种选择是仅导出传递给client.connect
回调的database
,并在整个应用程序的不同位置直接使用它。但是,无论 OP 有什么顾虑,我都建议不要这样做。
类似的,可能重复的 *** 问题,等等:
How to manage mongodb connections in nodejs webapp Node.JS and MongoDB, reusing the DB object Node.JS - What is the right way to deal with MongoDB connections【讨论】:
我已经考虑过您给出的解决方案,但没有继续这样做,因为正如我上面所说,我有大约 6 个集合以及必须在一个大闭包中编写所有操作的想法。其次,在您的方法中,有可能建立多个连接,因为它不会检查是否已连接。 不管你require(./dbmanager)' it will not call
client.connect`多少次。建立多个连接的唯一“机会”是运行多个服务器实例。 Node.JS 将仅在第一次需要时执行代码,每次后续调用仅返回 exports
。
-1 缺乏解释。与您的评论相反,您从未在问题中提及任何有关单个闭包的内容。我专门回答了你的每一个问题:它们是关于你是否应该在多个不同的文件中创建连接。我坚持我的回答:没有必要。
是的,我没有在问题中提到它,但这不是一个好的做法,我确实觉得明确写下关于遵循好的做法并不重要。编辑您的答案以避免问题,我也可以接受答案。
感谢您的声明性回答.....我真的很感激。这正是我自己完成的解决方案。很抱歉我之前给出的 -1 但我现在已将其恢复为 +1。我希望你也对这个问题做同样的事情。以上是关于在 express.js 中连接到 Mongodb-Native-Driver的主要内容,如果未能解决你的问题,请参考以下文章
在单独的 docker 容器 (AWS ECS) 中连接到 MongoDB
无法在 Spring Boot 应用程序中连接到 MongoDB
node.js + express.js:使用 mongodb/mongoose 处理会话
在 Express.js 应用程序中打开多个 MongoDB 连接