thinkjs项目中使用mongoose需要注意的地方
原文链接thinkjs项目中使用mongoose需要注意的地方
由于thinkjs不支持mongodb的关联模型查询,所以我不得不使用mongoose这个第三方odm。
我有两个选择,一是像我在express框架中那样使用mongoose,具体可以看我的项目源码https://github.com/xwlyy/express-blog。这种方法比较简单粗暴。
二是照着李大大在ThinkJS 项目里如何使用 Mongoose这篇博客中推荐的那样写,这种方法就比较美观。
每一个工程师都有保持代码优雅的义务,所以我选择了后者。不过李大大博客中的代码有不少错误,可能是没有做实例测试的缘故吧。我把碰到的问题整理了一下,现在分享给大家。还是推荐大家照着李大大的博客先操作一遍,碰到问题后再来看我的博客效果会比较好。
错误代码基本就集中在这一段
getModel(){
if(!this._model){
let connection = this.getConnection();
this._model = connection.model(this.name, new mongoose.Schema(this.schema));
}
return this._model;
}
第一个问题,new mongoose.Schema(this.schema)
这里少了个参数
正确代码应该是new mongoose.Schema(this.schema, {collection: this.name})
第二个参数{collection: this.name}
其实就是告诉mongoose去连接数据库中的哪个collection,我的collection名和model名是一样的,所以我直接用this.name
作为collection的属性值传进去。如果不一样的话还要另做处理。
第二个问题,if(!this._model)
每次访问都会判断为true
,也就是说每次访问都会创建一个新的数据库连接和新的model。
更要命的是代码不会直接报错,所有数据库操作都会正常进行。直到我看到本地数据库打开了80多个连接时我才意识到这段代码有问题。针对这个问题我并没有很好的解决方案,我后来是用了其他办法绕过了这个问题。
这段代码其实很容易看明白,如果没有问题的话,第二次访问应该是直接返回this._model
。可即使是这样,还是有问题,就是我下面要说的第三个问题。
第三个问题,没法使用populate操作。
我博客就三个collection,user、blog、comment。blog和comment中引用了user,以blog为例
schema= {
title: String,
content: String,
user: {type: mongoose.Schema.Types.ObjectId, ref: 'user'},
create_time: Number,
update_time: Number
}
当我使用populate查询时就报错,说没有注册user这个Schema。
if(!this._model){
let connection = this.getConnection();
this._model = connection.model(this.name, new mongoose.Schema(this.schema));
}
原因是这段代码为每一个model都创建了一个连接,我有3个model,每一个model的Schema都注册在各自的数据库连接中。如果各查各的这当然没有问题,但如果要用populate查询那就需要把Schema注册在同一个连接中。
我没有深入研究过mongoose,上面这段是我的猜测,仅供参考。
第四个问题,let connection = this.getConnection()
。
getConnection(){
let user = "";
if(this.config.user){
user = this.config.user + ":" + this.config.password + "@";
}
let host = this.config.host || "127.0.0.1";
let port = this.config.port || 27017;
let str = `mongodb://${user}${host}:${port}/${this.config.database}`;
return mongoose.createConnection(str);
}
问题出在return mongoose.createConnection(str);
我google了下,当需要连接多个数据库时用createConnection,只有一个数据库时用connect。李大大博客中也提到多配置连接需要用createConnection,但这段代码我没看出怎么获取多配置然后分别创建连接,意思应该还是连接单个数据库。所以正确的用法应该是把return mongoose.createConnection(str);
换成return mongoose.connect(str);
。
另外
if(!this._model){
let connection = this.getConnection();
this._model = connection.model(this.name, new mongoose.Schema(this.schema));
}