在express.js中连接到Mongodb-Native-Driver
我在express.js应用程序中使用mongodb本地驱动程序。 我在数据库中有大约6个集合,所以我创build了6个js文件,每个文件都有一个作为javascript对象的集合(例如, function collection(){}
),原型函数处理这些集合的所有操作。 我认为这将是一个很好的build筑。
但是我遇到的问题是如何连接到数据库? 我应该在每个文件中创build一个连接并使用它们吗? 我认为这将是一个矫枉过正的问题,因为mongodb-native-driver中的连接创build了一个连接池,其中有几个连接是不合理的。
那么如何创build一个连接池并将其用于所有collections.js文件? 我想要像在mongoose中实现的连接。 让我知道,如果我的应用程序的体系结构的任何思维过程是错误的。
使用Mongoose可以解决这些问题,但是我已经在几个地方读过,它比native-driver慢,我也更喜欢一个无模式的模型。
编辑:我用模型创build了一个模块。 每个集合都在一个文件中,并将数据库作为参数。 现在在index.js文件中,我调用了数据库连接,并在从连接中获取数据库后保留了一个variablesdb。 ( 我使用了自动重新连接function来确保连接没有丢失 )。 在同一个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
fincdbyid()
whatever you do in the function is upto you to implement
)。
如何连接到数据库?
为了使用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 } });
一个基本的连接是这样设置的。 这就是我可以给你的只是你想要的基本描述。 发布一些你已经得到的代码,以获得更具体的帮助。
我应该在每个文件中创build一个连接并使用它们吗?
没有。
那么如何创build一个连接池并将其用于所有collections.js文件?
你可以用上面的代码创build一个单独的文件,让我们把它dbmanager.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链接中查找这个更多的确认。 OP也在这个问题中说明了这一点。 这意味着client.connect
只能由服务器的一个实例调用一次 。 database
对象从调用client.connect
成功检索后,该database
对象应该在应用程序的整个实例中重用。 这很容易通过使用Node.JS提供的模块模式来完成。
我的build议是创build一个模块或一组模块作为与数据库交互的单一联系点。 在我的应用程序中,我通常有一个依赖本机驱动程序的模块,调用require('mongodb')
。 我的应用程序中的所有其他模块不会直接访问数据库,而是所有操作必须由此数据库模块进行协调。
这将处理本地驱动程序的所有代码封装到单个模块或一组模块中。 OP似乎认为我所发布的简单代码示例存在一个问题,在我的示例中描述了一个“单个大闭包”的问题。 这是非常基本的东西,所以我在这里添加了关于基本架构的说明,但是我仍然不觉得需要更改任何代码。
OP也似乎认为可能在这里build立多个连接。 这是不可能的这个设置。 如果你创build了一个像我上面build议的模块,那么第一次require('./dbmanager')
被调用时,它将执行文件dbmanager.js
的代码并返回module.exports
对象。 exports对象被caching,并且在每次后续调用require('./dbmanager')
,但是, dbmanager.js
的代码只会执行第一个require
。
如果你不想创build一个这样的模块,那么另外一个select就是只导出传递给client.connect
callback的database
,并在整个应用程序的不同位置直接使用它。 不过,我反对这个build议,不pipeOP的问题。
类似的,可能复制Stackoverflow的问题,其中包括:
- 如何在nodejs webapp中pipe理mongodb连接
- Node.JS和MongoDB,重用DB对象
- Node.JS – 处理MongoDB连接的正确方法是什么?
正如接受的答案所说 – 你应该只为所有传入的请求创build一个连接,并重用它,但答案是缺less解决scheme,这将创build和caching连接。 我写了快递中间件来实现这个 – express-mongo-db 。 乍一看这个任务是微不足道的,大多数人使用这种types的代码:
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
一次connect
来解决此问题。
希望你觉得它有用。
我只是认为我会添加自己的MongoDB连接方法为其他感兴趣的人或有不同的方法的问题
这个方法假定你不需要authentication(我在本地主机上使用这个)
authentication仍然很容易实现
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)在他的着作 (231-232页)中介绍了这种方法,
- 由于node.js延迟响应,连接超时
- Elasticsearch分页与MongoDB和ExpressJS
- 服务器重新启动后,通过身份validation的用户login
- 将jQuery ajax调用转换为vanilla Javascript – 不能POST / public / error
- 如何将jwtauthentication与ACL混合
- Express Js不在res.json()上发送错误对象
- 连接到服务器时,浏览器是否自动请求index.html?
- 在不超过堆栈限制的情况下,通过大量庞大的函数进行迭代或recursion的最佳方法是什么?
- 向本地主机请求远程服务器获取预检请求'Access-Control-Allow-Origin'