Eggjs使用Sequelize (ORM)插件操做MySQL

Eggjs 連接 MySQL & Sequelize (ORM)

使用Eggjs連接MySQL能夠使用Sequelizehtml

sequelize 是一個普遍使用的 ORM 框架,它支持 MySQL、PostgreSQL、SQLite 和 MSSQL 等多個數據源。mysql

npm install --save egg-sequelize mysql2
複製代碼

配置插件

config/plugin.jsgit

sequelize: {
  enable: true,
    package: 'egg-sequelize',
},
複製代碼

設置參數

config/config.default.jsgithub

// sequelize
config.sequelize = {
  dialect: 'mysql',
  host: '127.0.0.1',
  port: 3306,
  database: 'egg-db',
  username: 'root', // 數據庫用戶名
  password: '12345678', // 數據庫密碼
  timezone: '+08:00', // 設置時區
  define: {
    timestamps: true, // 自動寫入時間戳 created_at updated_at
    paranoid: true, // 字段生成軟刪除時間戳 deleted_at
    underscored: true, // 全部駝峯命名格式化
  },
};
複製代碼

建立數據庫

CREATE DATABASE IF NOT EXISTS `egg-db`;
複製代碼

數據遷移

sequelize 提供了 sequelize-cli 工具來實現 Migrationssql

安裝sequelize-cli

npm install --save-dev sequelize-cli
複製代碼

將全部數據庫 Migrations 相關的內容都放在 database 目錄下,在項目根目錄下新建一個 .sequelizerc 配置文件數據庫

.sequelizercnpm

'use strict';

const path = require('path');

module.exports = {
  config: path.join(__dirname, 'database/config.json'),
  'migrations-path': path.join(__dirname, 'database/migrations'),
  'seeders-path': path.join(__dirname, 'database/seeders'),
  'models-path': path.join(__dirname, 'app/model'),
};
複製代碼

初始化 Migrations 配置文件和目錄

npx sequelize init:config
npx sequelize init:migrations
複製代碼

執行完後會生成 database/config.json 文件和 database/migrations 目錄json

修改 database/config.json 中的內容,將其改爲項目中使用的數據庫配置api

database/config.jsonbash

{
  "development": {
    "dialect": "mysql",
    "host": "127.0.0.1",
    "port": 3306,
    "database": "egg-db",
    "username": "root",
    "password": "12345678"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}
複製代碼

建立並編寫Migration 文件來建立表

npx sequelize migration:generate --name=init-users
複製代碼

執行完後會在 database/migrations 目錄下生成一個 migration 文件(${timestamp}-init-users.js)

database/migrations/202104****-init-users.js

'use strict';

module.exports = {
  // 在執行數據庫升級時調用的函數,建立 users 表
  up: async (queryInterface, Sequelize) => {
    const { INTEGER, STRING, DATE, DECIMAL } = Sequelize;
    await queryInterface.createTable('users', {
      id: { type: INTEGER, primaryKey: true, autoIncrement: true },
      user_name: {
        type: STRING,
        allowNull: false,
        unique: true,
        comment: '用戶名,惟一',
      },
      pass_word: STRING,
      gender: {
        type: DECIMAL,
        allowNull: false,
        defaultValue: 3,
        comment: '性別(1 男性,2 女性,3 保密)',
      },
      birthday: DATE,
      city: STRING,
      picture: STRING,
      created_at: DATE,
      updated_at: DATE,
      deleted_at: DATE,
    });
  },

  down: async queryInterface => {
    await queryInterface.dropTable('users');
  },
};
複製代碼

執行 migrate 進行數據庫變動 建立表

# 升級數據庫
npx sequelize db:migrate
# 若是有問題須要回滾,能夠經過 `db:migrate:undo` 回退一個變動
# npx sequelize db:migrate:undo
# 能夠經過 `db:migrate:undo:all` 回退到初始狀態
# npx sequelize db:migrate:undo:all
複製代碼

實踐demo

用戶表 關注表 用戶 粉絲 一對多關係

建立關注關係表

npx sequelize migration:generate --name=init-userfollows
複製代碼

編寫Migration

database/migrations/202104****-init-Userfollow.js

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    const { INTEGER, DATE } = Sequelize;
    await queryInterface.createTable('userfollows', {
      id: { type: INTEGER, primaryKey: true, autoIncrement: true },
      user_id: {
        type: INTEGER,
        allowNull: false,
        comment: '用戶的 id',
      },
      follower_id: {
        type: INTEGER,
        allowNull: false,
        comment: '被關注用戶的 id',
        // 外鍵 用戶表ID
        references: {
          model: 'users',
          key: 'id',
        },
      },
      created_at: DATE,
      updated_at: DATE,
      deleted_at: DATE,
    });
  },

  down: async queryInterface => {
    await queryInterface.dropTable('userfollows');
  },
};
複製代碼
# 升級數據庫
npx sequelize db:migrate
複製代碼

建立關注關係模型

app/model/userfollow.js

'use strict';

module.exports = app => {
  const { INTEGER } = app.Sequelize;

  const Userfollow = app.model.define('userfollows', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true },
    userId: INTEGER,
  });

  Userfollow.associate = () => {
    // 一對一關係 每一個 followerId 對應一個用戶
    Userfollow.belongsTo(app.model.User, {
      foreignKey: 'followerId',
      targetKey: 'id',
    });
  };

  return Userfollow;
};
複製代碼

建立用戶模型

app/model/users.js

'use strict';

module.exports = app => {
  const { STRING, INTEGER, DECIMAL, DATE } = app.Sequelize;

  const User = app.model.define('users', {
    id: { type: INTEGER, primaryKey: true, autoIncrement: true },
    userName: {
      type: STRING,
      allowNull: false,
      unique: true,
      comment: '用戶名,惟一',
    },
    passWord: STRING,
    gender: {
      type: DECIMAL,
      allowNull: false,
      defaultValue: 3,
      comment: '性別(1 男性,2 女性,3 保密)',
    },
    birthday: DATE,
    city: STRING,
    picture: STRING,
  });

  User.associate = () => {
    // 一對多關係 一個用戶有多個粉絲
    User.hasMany(app.model.Userfollow, {
      foreignKey: 'userId',
      targetKey: 'followerId',
    });
  };

  return User;
};

複製代碼

實現查詢粉絲、關注 API

查詢用戶的粉絲

app/controller/userfollow.js

// 獲取粉絲列表
async getFans() {
  const { ctx } = this;
  const data = await ctx.service.userfollow.getUsersByFollower(ctx.params.id, ctx.request.query);
  ctx.body = { status: true, msg: '粉絲列表獲取成功', data };
}
複製代碼

app/service/userfollow.js

// ***
const { Op } = require('sequelize');
const { toInt } = require('../extend/utils'); // toInt 將字符串轉爲數值型
// ***

async getUsersByFollower(followerId, query) {
  const { pageNumber = 1, pageSize = 10 } = query;
  const result = await this.ctx.model.User.findAndCountAll({
    limit: toInt(pageSize),
    offset: toInt(pageSize) * (toInt(pageNumber) - 1),
    attributes: [ 'id', 'userName', 'picture', 'city', 'gender' ],
    order: [[ 'id', 'desc' ]],
    include: [
      {
        model: this.ctx.model.Userfollow,
        attributes: [ ],
        where: {
          followerId,
          userId: {
            [ Op.ne]: followerId,
          },
        },
      },
    ],
  });
  return result;
}
複製代碼

查詢用戶的關注

app/controller/userfollow.js

// 獲取關注列表
async getFollowers() {
  const { ctx } = this;
  const data = await ctx.service.userfollow.getFollowersByUser(ctx.params.id, ctx.request.query);
  ctx.body = { status: true, msg: '關注列表獲取成功', data };
}
複製代碼

app/service/userfollow.js

async getFollowersByUser(userId, query) {
  const { pageNumber = 1, pageSize = 10 } = query;
  const result = await this.ctx.model.Userfollow.findAndCountAll({
    limit: toInt(pageSize),
    offset: toInt(pageSize) * (toInt(pageNumber) - 1),
    order: [[ 'id', 'desc' ]],
    attributes: [ ],
    include: [
      {
        model: this.ctx.model.User,
        attributes: [ 'id', 'userName', 'picture', 'city', 'gender' ],
      },
    ],
    where: {
      userId,
      followerId: {
        [Op.ne]: userId,
      },
    },
  });
  return result;
}
複製代碼

路由

app/router.js

router.get('/api/v1/user/:id/fans', controller.userfollow.getFans); // 獲取用戶的粉絲列表
router.get('/api/v1/user/:id/follow', controller.userfollow.getFollowers); // 獲取用戶的關注列表
複製代碼

在表中插入幾條測試數據

// ***
複製代碼

訪問路由

// GET http://127.0.0.1:7001/api/v1/user/1/fans?pageNumber=1&pageSize=10
{
    "status": true,
    "msg": "粉絲列表獲取成功",
    "data": {
        "count": 2,
        "rows": [
            {
                "id": 3,
                "userName": "test3",
                "picture": null,
                "city": "杭州",
                "gender": "1"
            },
            {
                "id": 2,
                "userName": "test2",
                "picture": null,
                "city": "上海",
                "gender": "3"
            }
        ]
    }
}

// http://127.0.0.1:7001/api/v1/user/3/follow?pageNumber=1&pageSize=10
{
    "status": true,
    "msg": "關注列表獲取成功",
    "data": {
        "count": 1,
        "rows": [
            {
                "user": {
                    "id": 1,
                    "userName": "test1",
                    "picture": null,
                    "city": "北京",
                    "gender": "3"
                }
            },
        ]
    }
}
複製代碼

Sequelize 的 crud

const result = await this.ctx.model.Userfollow.create({
  userId,
  followerId,
});
複製代碼

const result = await this.ctx.model.Userfollow.destroy({
  where: {
    userId,
    followerId,
  },
});
複製代碼

// ...
const user = await this.ctx.model.User.findByPk(id);
// ...
await user.update({ userName, gender, birthday, city, picture });
複製代碼

const result = await this.ctx.model.Userfollow.findOne({
  where: {
    userId,
    followerId,
  },
});
複製代碼

關於更多Sequelize的用法 訪問 www.sequelize.com.cn/

image.png

---END---

相關文章
相關標籤/搜索