原文链接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));
}

还需要在这段代码中再加一层条件判断,如果已创建连接则使用当前连接,如果没有则新建连接。否则就会报错,说你试图打开已打开的数据库连接。

然而,事实上这个问题我还是没有解决,因为我不知道该怎么判断mongoose是否已创建连接。我用了别的办法绕过了这个问题,三言两语说不清,还是得看我的项目源码https://github.com/xwlyy/thinkjs-blog

实际DEBUG过程中碰到的问题远比这多的多,但最后总结下来差不多就这四条。另外,我对自己最后的解决方案也不是很满意,特别是我把数据库连接放在blog控制器里,这显然是一种非常蛋疼的写法。还是需要想办法解决我前面提到的那两个我没有解决的问题,李大大博客中的写法才是最完美的。

thinkjs项目中使用mongoose需要注意的地方的更多相关文章

  1. Mongo基础使用,以及在Express项目中使用Mongoose

    MongoDB的基本使用 MongoDB特点: 使用BSON存储数据 支持相对丰富的查询操作(相对其他nosql数据库) 支持索引 副本集(支持多个实例/多个服务器运行同个数据库) 分片(数据库水平扩 ...

  2. android项目中导入actionbarsherlock 需要注意的地方

    1,在导入actionbarsherlock 这个library时,如果一直报" Invalid Project Description" ;  解决办法:  android中li ...

  3. laravel项目中手机浏览器在线阅读pdf文件-->PDFJS插件

    第一步:下载链接:http://mozilla.github.io/pdf.js/getting_started/#download 第二步:将下载的文件放在项目中. 第三步:在项目中想要预览的地方给 ...

  4. 转:C++项目中的extern "C" {}

    引言 在用C++的项目源码中,经常会不可避免的会看到下面的代码: #ifdef __cplusplus extern "C" { #endif /*...*/ #ifdef __c ...

  5. 在WebStorm环境中给nodejs项目中添加packages

    照前文 http://www.cnblogs.com/wtang/articles/4133820.html  给电脑设置了WebStorm的IDE的nodejs开发环境.新建了个express的网站 ...

  6. C++项目中的extern "C" {}

    from:http://www.cnblogs.com/skynet/archive/2010/07/10/1774964.html C++项目中的extern "C" {} 20 ...

  7. [转] C++项目中的extern "C" {}

    点击阅读原文 引言 在用C++的项目源码中,经常会不可避免的会看到下面的代码: #ifdef __cplusplus extern "C" { #endif /*...*/ #if ...

  8. VS项目中使用Nuget还原包后编译生产还一直报错?

    Nuget官网下载Nuget项目包的命令地址:https://www.nuget.org/packages 今天就遇到一个比较奇葩的问题,折腾了很久终于搞定了: 问题是这样的:我的解决方案原本是好好的 ...

  9. ABP项目中使用Swagger生成动态WebAPI

    本文是根据角落的白板报的<使用ABP实现SwaggerUI,生成动态webapi>一文的学习总结,感谢原文作者角落的白板报. 1 安装Swashbuckle.core 1.1 选择WebA ...

随机推荐

  1. Sql2008 全文索引创建

    在SQL Server 中提供了一种名为全文索引的技术,可以大大提高从长字符串里搜索数 据的速度,不用在用LIKE这样低效率的模糊查询了.   下面简明的介绍如何使用Sql2008 全文索引 一.检查 ...

  2. Spring 源码学习(3) —— 增加属性注册编辑器

    创建一个实体类UserManager: /** * @filename: UserManager.java * @desc 增加属性编辑器功能测试实体类 * @author: Wang Chinda ...

  3. matlab的rem()和mod()函数

    matlab的rem()和mod()函数 rem(x,y):求整除x/y的余数 mod(x,y):求模 rem(x,y)=x-y.*fix(x./y);  (fix()向0取整) mod(x,y)=x ...

  4. 《JavaScript 实战》:JavaScript 实现图片切割效果

    很久之前就在一个网站的截取相片的功能中看到这个效果,也叫图片裁剪.图片剪切(设置一下也可以做出放大镜等类似的效果).当时觉得很神奇,碍于水平有限,没做出来.前些日子突然想做一个透镜效果,就突然想到了这 ...

  5. ASP .NET登录界面用户验证码代码

    //ASP .NET用户登录界面经常用到验证码代码如下 private void Page_Load(object sender, System.EventArgs e) { // 在此处放置用户代码 ...

  6. 【CodeForces】932 E. Team Work

    [题目]E. Team Work [题意]给定n和k,n个人中选择一个大小为x非空子集的代价是x^k,求所有非空子集的代价和%1e9+7.n<=10^9,k<=5000. [算法]斯特林反 ...

  7. POJ 1050 To the Max (最大子矩阵和)

    题目链接 题意:给定N*N的矩阵,求该矩阵中和最大的子矩阵的和. 题解:把二维转化成一维,算下就好了. #include <cstdio> #include <cstring> ...

  8. ActiveMQ笔记之安装(Linux)

    1. 基本概念 MQ(MessageQueue),消息队列,是一个消息接收和转发的容器. Apache ActiveMQ是一个JMS Provider实现. 2. 安装 从官网下载安装包: wget ...

  9. sublime出现卡顿的现象

    这几天,用sublime总是写一个代码就卡顿,卡卡卡,,,,要死的~ 最后,才发现是因为安装了一个插件:GitGutter插件,所以,小伙伴们请跟上我的节奏~~~~~ (1)Ctrl + Shift ...

  10. D - Binary Lexicographic Sequence URAL - 1081 (贪心)

    题目链接:https://cn.vjudge.net/contest/275079#problem/D 具体思路:首先,我们可以观察到1-n位数的种数连起来是一个很有规律的数列,然后我们开始倒序建立. ...