zoukankan      html  css  js  c++  java
  • 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));
        }

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

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

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

  • 相关阅读:
    Best Time to Buy and Sell Stock
    Remove Nth Node From End of List
    Unique Paths
    Swap Nodes in Pairs
    Convert Sorted Array to Binary Search Tree
    Populating Next Right Pointers in Each Node
    Maximum Subarray
    Climbing Stairs
    Unique Binary Search Trees
    Remove Duplicates from Sorted Array
  • 原文地址:https://www.cnblogs.com/zzsdream/p/6957306.html
Copyright © 2011-2022 走看看