Mongoose模型如何与MongoDB连接?为何未导入连接仍可执行save()?
save()保存文档? 我通过mongoose.model()创建了user集合对应的模型,存于单独文件models/user.js;使用Mongoose创建的MongoDB连接实例则存于db/mongoose.js文件。两者均被导入到server.js中支撑Web应用运行,代码如下:
var express = require('express'); var bodyParser = require('body-parser'); var {mongoose} = require('./db/mongoose'); var {User} = require('./models/user'); var app = express(); app.use(bodyParser.json()); app.post('/todos', (req, res) => { var user = new User({ text: req.body.text }); user.save().then((doc) => { res.send(doc); }, (e) => { res.status(400).send(e); }); }); app.listen(3000, () => { console.log('Started on port 3000'); }); module.exports = {app};
这里的{mongoose}和{User}看起来像是独立实体,而且models/user.js并未导入./db/mongoose.js,既然user model是静态内容,为什么user.save()能连接数据库并保存文档?
解答
这其实是Mongoose的核心设计之一:模型会自动关联全局初始化的数据库连接,不需要每个模型文件都手动导入连接实例。具体来说:
全局连接池的作用
当你在server.js中导入./db/mongoose.js时,这个文件里的代码应该已经执行了mongoose.connect()(或者类似的连接初始化代码),这一步会让Mongoose在内部创建一个全局的数据库连接池。这个连接池是Mongoose全局共享的,所有后续创建的模型都会默认使用它。模型的全局注册
在models/user.js里,你调用mongoose.model('User', userSchema)创建模型时,Mongoose会把这个模型注册到自己的全局上下文环境中。这个上下文已经和之前初始化的全局连接池绑定在了一起,所以模型本身就“知道”该用哪个连接来操作数据库。无需显式传递连接
当你在server.js中导入User模型后,它已经是一个和全局连接关联好的模型实例了。所以调用user.save()时,模型会直接使用全局连接池里的连接来和MongoDB通信,完全不需要在模型文件里单独导入./db/mongoose.js。
简单来说,Mongoose帮你做了“连接共享”的底层工作,你只需要确保在使用模型之前,已经初始化好数据库连接就行——这也是为什么我们通常会在应用入口(比如server.js)里先导入连接文件,再导入模型的原因。
内容的提问来源于stack exchange,提问作者Prem

