【DB】快速集成MongoDB & MySQL

548 阅读2分钟

集成 MongoDB

安装mongoDB

首先确保电脑中已安装并启动 MongoDB 数据库,如果是 Mac 电脑,可以用下面的命令快速安装和启动:

$ brew install mongodb-community
$ brew services start mongodb/brew/mongodb-community # 后台启动
# 或者使用 
$ mongod --config /usr/local/etc/mongod.conf 前台启动

定义连接参数

config = {
  client: {
    url: 'mongodb://127.0.0.1/example',
    options: {}
  }
}

然后在 model/user.js 中定义模型:

module.exports = app => {
  const mongoose = app.mongoose
  //定义表结构
  const UserSchema = new mongoose.Schema(
    {
      username: {type: String, required: true, unique: true}, // 用户名
      password: {type: String, required: true}, // 密码
    },
    { timestamps: true } // 自动生成 createdAt 和 updatedAt 时间戳
  )
  //  生成名为User的mongoDB Model
  //  后续操作都是基于该 Model
  return mongoose.model('user', UserSchema)
}

在Controller或Service中调用 mongoose 的方法:

const {Controller} = require('egg')

class UserController extends Controller {
  // 用户列表 GET /users
  async index() {
    const {ctx} = this
    ctx.body = await ctx.model.User.find({})
  }

  // 用户详情 GET /users/:id
  async show() {
    const {ctx} = this
    ctx.body = await ctx.model.User.findById(ctx.params.id)
  }

  // 创建用户 POST /users
  async create() {
    const {ctx} = this
    ctx.body = await ctx.model.User.create(ctx.request.body)
  }

  // 更新用户 PUT /users/:id
  async update() {
    const {ctx} = this
    ctx.body = await ctx.model.User.findByIdAndUpdate(ctx.params.id, ctx.request.body)
  }

  // 删除用户 DELETE /users/:id
  async destroy() {
    const {ctx} = this
    ctx.body = await ctx.model.User.findByIdAndRemove(ctx.params.id)
  }
}

module.exports = UserController

集成 MySQL

安装 MySQL

首先确保电脑中已安装 MySQL 数据库,如果是 Mac 电脑,可通过下面的命令快速安装和启动:

$ brew install mysql
$ brew services start mysql # 后台启动
# 或者 mysql.server start 前台启动
$ mysql_secure_installation # 设置密码

定义连接参数

config = {
  client: {
    host: 'localhost',
    port: '3306',
    user: 'root',
    password: 'root',
    database: 'cms',
  }
}

在 Controller 或 Service 中获取到 mysql 对象

class UserService extends Service {
  async find(uid) {
    const user = await this.app.mysql.get('users', { id: 11 });
    return { user }
  }
}

如果启动的时候报错:

ERROR 5954 nodejs.ER_NOT_SUPPORTED_AUTH_MODEError: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client

是因为你使用了 MySQL 8.x 版本,而 egg-mysql 依赖了 ali-rds 这个包,这是阿里自己封装的包,里面又依赖了 mysql 这个包,而这个包已经废弃,不支持 caching_sha2_password 加密方式导致的。可以在 MySQL workbench 中运行下面的命令来解决:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password'
flush privileges

sequelize

但是更好的集成 MySQL 的方式是借助 ORM 框架来帮助我们管理数据层的代码,sequelize 是当前最流行的 ORM 框架,它支持 MySQL、PostgreSQL、SQLite 和 MSSQL 等多个数据源,接下来我们使用 sequelize 来连接 MySQL 数据库,首先安装依赖:

npm install egg-sequelize mysql2 --save 
yarn add egg-sequelize mysql2

然后在 config/plugin.js 中开启 egg-sequelize 插件:

exports.sequelize = {
  enable: true,
  package: 'egg-sequelize',
}
复制代码

同样要在 config/config.default.js 中编写 sequelize 配置

config.sequelize = {
  dialect: 'mysql',
  host: '127.0.0.1',
  port: 3306,
  database: 'example',
}

然后在 egg_example 库中创建 books 表:

CREATE TABLE `books` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'primary key',
  `name` varchar(30) DEFAULT NULL COMMENT 'book name',
  `created_at` datetime DEFAULT NULL COMMENT 'created time',
  `updated_at` datetime DEFAULT NULL COMMENT 'updated time',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='book';

创建 model/book.js 文件,代码是:

module.exports = app => {
  const { STRING, INTEGER } = app.Sequelize
  const Book = app.model.define('book', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true },
    name: STRING(30),
  })
  return Book
}

添加 controller/book.js 控制器:

const Controller = require('egg').Controller

class BookController extends Controller {
  async index() {
    const ctx = this.ctx
    ctx.body = await ctx.model.Book.findAll({})
  }

  async show() {
    const ctx = this.ctx
    ctx.body = await ctx.model.Book.findByPk(+ctx.params.id)
  }

  async create() {
    const ctx = this.ctx
    ctx.body = await ctx.model.Book.create(ctx.request.body)
  }

  async update() {
    const ctx = this.ctx
    const book = await ctx.model.Book.findByPk(+ctx.params.id)
    if (!book) return (ctx.status = 404)
    await book.update(ctx.request.body)
    ctx.body = book
  }

  async destroy() {
    const ctx = this.ctx
    const book = await ctx.model.Book.findByPk(+ctx.params.id)
    if (!book) return (ctx.status = 404)
    await book.destroy()
    ctx.body = book
  }
}

module.exports = BookController

最后配置 RESTful 路由映射:

module.exports = app => {
  const {router, controller} = app
  router.resources('books', '/books', controller.book)
}