Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

sequelize-cli配置(用于管理migration)

安装+前置配置

  • 进入项目目录,打开命令行

    • 安装sequelize-cli数据库迁移插件
      cnpm install sequelize-cli -S
      
  • 想把 Migrations 相关内容都放在 database 目录下

    • 所以要进入根目录,新建.sequelizerc配置文件

      '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
    npx sequelize init:seeders
    
    • 不需要用原生方式初始化模型npx sequelize init:models
  • 配置config.json,填入数据库名字和密码

    "development": {
        "username": "root",
        "password": "123456",
        "database": "book_list",
        "host": "127.0.0.1",
        "dialect": "mysql",
        "port": "3306"
      },
    

 

初始化迁移文件并执行

  • 命令行创建 Books表 的迁移文件(${timestamp}-init-books.js)

    npx sequelize migration:generate --name=init-books
    
  • 找到database/migrations/xxxx-init-books.js,新增内容:

    //在up函数内填写
    const { STRING, INTEGER, DATE} = Sequelize;
    
    await queryInterface.createTable("books", {
        id:{
            type:INTEGER,
            primaryKey: true,
            autoIncrement: true,
        },
        title: STRING(50),
        author: STRING(50),
        price: STRING(10),
        page_count: STRING(10),
        publisher: STRING(50),
        content:STRING(800),
        img: STRING(100),
        origin_title: STRING(50),
        hz_lib_code: STRING(20),
    });
    
    //在down函数内填写
    await queryInterface.dropTable('books');
    
  • 命令行执行迁移

    npx sequelize db:migrate
    
    • 如果有问题要回滚,可以执行
      npx sequelize db:migrate:undo
      
    • 或者直接回滚到初始状态
      npx sequelize db:migrate:undo:all
      

初始化种子并执行

  • 命令行创建Books表的填充文件(${timestamp}-bookSeeder.js)

    npx sequelize seed:generate --name=bookSeeder
    
  • 找到database/seeders/xxxx-bookSeeder.js

    //在up函数内填写
    await queryInterface.bulkInsert('books',[
        {
            数据1的对象键值对
        },
        {
            数据2的对象键值对
        },
    ])
    
    //在down函数内填写
    return queryInterface.bulkDelete('books', null, {});
    
  • 命令行执行填充

    npx sequelize db:seed:all
    
    • 如果有问题要撤销填上一步的种子
      npx sequelize db:seed:undo
      
    • 或者直接撤销所有种子
      npx sequelize-cli db:seed:undo:all
      
    • 或者撤销特定种子
      npx sequelize-cli db:seed:undo --seed 种子名
      

初始化模型并执行

这里不能用原生sequelize方式去写model!巨坑!特别是初始化index.js和创建book后自动生成的文件,根本就不能正常在eggjs中运行,压根就不会挂载到ctx.model上面

  • 【正确做法】

    module.exports = app => {
        const { STRING, INTEGER, DATE} = app.Sequelize;
    
        //定义数据表结构
        const User = app.model.define('user',{
            键值对
        });
    
        //定义对象方法
        User.方法名 = async function(login){
    
        }
    
        //定义实例方法
        User.prototype.方法名 = async function() {
    
        }
    }
    
  • 【错误做法】

    • 当我们用命令行创建Books表的模型文件时

      npx sequelize model:generate --name=Book --attributes title:string
      
    • 同时会生成迁移文件(${timestamp}-create-book.js)

    • app/model/book.js中,有两种写法

    • 【法1】扩展Model(好像有bug)

      //改写init函数为如下模样,数据类型加上DataTypes.来获取
      Book.init({
          title: DataTypes.STRING,
          id:{
            type:DataTypes.INTEGER,
            primaryKey: true,
            autoIncrement: true,
          },
          img: DataTypes.STRING,
          title: DataTypes.STRING,
          author: DataTypes.STRING,
          content: DataTypes.STRING,
          created_at: DataTypes.DATE,
          updated_at: DataTypes.DATE,
        }, {
          sequelize,
          modelName: 'Book',
        });
      
      • 注意,在以上方法中,都从未明确定义表名(Books). 但是,给出了模型名称(Book).会用inflection库自动计算出复数作为表名

      • 可以加参数freezeTableName: true,停止自动计算,这样就用模型名作为表名

      • 也可以加参数tableName: 'Books',直接提供表名

    • 【法2】直接define(这样好像是错的)

      const { Sequelize, DataTypes } = require('sequelize');
      const sequelize = new Sequelize('mysql::memory:');
      
      const Book = sequelize.define('Book',{
        id:{
          type:DataTypes.INTEGER,
          primaryKey: true,
          autoIncrement: true,
        },
        img: DataTypes.STRING,
        title: DataTypes.STRING,
        author: DataTypes.STRING,
        content: DataTypes.STRING,
        created_at: DataTypes.DATE,
        updated_at: DataTypes.DATE,
      }, {
      });
      
      
  • 控制器或者服务中调用

    await this.ctx.model.Book.findAll()
    

创建表关联

新增列迁移文件并执行

  • 命令行创建Books表的新增列迁移文件(${timestamp}-add-column-books.js)

    npx sequelize migration:generate --name=add-column-books
    
  • 找到database/migrations/xxxx-add-column-books.js

    //在up函数内填写
    const { STRING, BOOLEAN} = Sequelize;
    
    return queryInterface.sequelize.transaction(async t => {
        try{
            await queryInterface.addColumn("books","choice",{
                    type: BOOLEAN,
                    defaultValue: true
                },
                { transaction: t}
            );
    
            await queryInterface.addColumn("books","home_tag",{
                    type: STRING(10),
                    defaultValue: "无",
                },
                { transaction: t}
            );
    
            return Promise.resolve(e)
        }catch(e){
            return Promise.reject(e)
        }
    })
    
    //在down函数内填写
    return queryInterface.sequelize.transaction(async t => {
        try{
            await queryInterface.addColumn("books","choice");
    
            await queryInterface.removeColumn("books","home_tag");
    
            return Promise.resolve(e)
        }catch(e){
            return Promise.reject(e)
        }
    })
    
  • 命令行执行迁移

    npx sequelize db:migrate
    
    • 如果有问题要回滚,可以执行
      npx sequelize db:migrate:undo
      
    • 或者直接回滚到初始状态
      npx sequelize db:migrate:undo:all