问题

这周有个需要是应用 egg.js 接入 MongoDB 数据库,于是先依照官网举荐的形式应用 egg-mongoose,然而在依照文档进行操作写 demo 时呈现了十分诡异的谬误TypeError: Cannot read property 'Schema' of undefinedapp.mongoose app 下的 mongoose 没有被失常挂载上。

// config/plugin.jsmodule.exports = {  ... 省略其余不相干配置  mongoose: {    enable: true,    package: 'egg-mongoose',  },};// config/config.default.jsmodule.exports = appInfo => {  /**   * built-in config   * @type {Egg.EggAppConfig}   **/  const config = exports = {};  ... 省略其余不相干配置  config.mongoose = {    client: {      url: 'mongodb://xxxx:30000',      options: {        mongos: true,        dbName: 'xxx',        user: 'xxx',        pass: 'xxx',      },    },  };  return {    ...config,  };}// {app_root}/app/model/user.jsmodule.exports = app => {  const mongoose = app.mongoose;  const Schema = mongoose.Schema;  const UserSchema = new Schema({    userName: { type: String  },    password: { type: String  },  });  return mongoose.model('User', UserSchema);}

排查思路

首先确认有没有拼写错误,没有的话间接用最小化形式应用 egg-mongoose 是否能够复现来确认是不是文档呈现了问题。测试后发现失常。接下来就是排查本地代码,发现是因为 egg-sequelize 导致的,而局部业务接口之前配置了应用 MySQL 数据库。 egg-sequelizeegg-mongoose 默认都是加载 app/model 下的文件,具体逻辑后续详说。

解决办法

看看是否能够批改插件的加载目录。
egg-mongoose 是不能配置的,源码外面写死了指定的 model 门路, egg-sequelize 是能够的。

config.sequelize = {    baseDir: 'my_model', // load all models to `app[delegate]` and `ctx[delegate]`, default to `model`    delegate: 'myModel', // load all models to `app[delegate]` and `ctx[delegate]`, default to `model`    dialect: 'mysql',    host: process.env.MYSQL_HOST,    port: 3306,    database: process.env.MYSQL_DATABASE    username: process.env.MYSQL_USER     password: process.env.MYSQL_PASSWORD};

批改之前就没问题了,delegate 示意将 orm 挂载的地位,之前默认是 model,批改完之后不要遗记业务代码中的已有代码(如this.ctx.model.xxx => this.ctx.myModel.xxx)。