美文网首页
umzug sequelize 数据迁移方案 by midway

umzug sequelize 数据迁移方案 by midway

作者: 吴占超 | 来源:发表于2021-12-30 14:50 被阅读0次

前言

sequelize-v6 版本是本人非常喜欢的ORM方案.
https://sequelize.org/v6/
借鉴数据迁移方案官方提供的方案使用umzug进行处理利用ts的特点降低开发难度!
https://github.com/sequelize/umzug
本次框架使用midway-v2
https://www.yuque.com/midwayjs/midway_v2/introduction
感谢🙇

使用方案 seed 与 db相同

  • 创建db model
# 创建
$ yarn umzug:c --name app-user.ts
# 迁移
$ yarn umzug:u [--name]
# 回滚
$ yarn umzug:d [--name]
  • package
# sequelize
$ yarn add @midwayjs/sequelize sequelize sequelize-typescript mysql2 -S 
# umzug
$ yarn add umzug -D
  • 引入模块
    \color{red} {configuration.ts} 文件中
import { App, Configuration } from '@midwayjs/decorator';
...
import * as sequlize from '@midwayjs/sequelize';

@Configuration({
  imports: [sequlize],
  importConfigs: [join(__dirname, './config')],
})
export class ContainerLifeCycle implements ILifeCycle {
  @App()
  app: Application;

  async onReady() {
    
  }
}
  • 模板代码
    package.json
{
  "scripts": {
    "umzug:h": "node database/migrator.js -h",
    "umzug:u": "node database/migrator.js up",
    "umzug:d": "node database/migrator.js down",
    "umzug:c": "node database/migrator.js create",
    "seed:h": "node database/migrator-seed.js -h",
    "seed:u": "node database/migrator-seed.js up",
    "seed:d": "node database/migrator-seed.js down",
    "seed:c": "node database/migrator-seed.js create",
  }
}

database/migrator.js

// eslint-disable-next-line node/no-unpublished-require
require('ts-node/register');

require('./umzug').migrator.runAsCLI();

database/migrator-seed.js

// eslint-disable-next-line node/no-unpublished-require
require('ts-node/register');

require('./umzug-seed').migrator.runAsCLI();

database/config.json
数据库配置

{
  "development": {
    "port": 53306,
    "host": "rm-xxx.mysql.zhangbei.rds.aliyuncs.com",
    "database": "xxx_dev",
    "username": "root",
    "password": "xxx",
    "dialect": "mysql",
    "define": {
      "charset": "utf8"
    },
    "logging": false
  },
  "dev": {
    "port": 53306,
    "host": "rm-xxx.mysql.zhangbei.rds.aliyuncs.com",
    "database": "xxx_stage",
    "username": "root",
    "password": "xxx",
    "dialect": "mysql",
    "define": {
      "charset": "utf8"
    },
    "logging": false
  },
  "pre": {
    "port": 53306,
    "host": "rm-xxx.mysql.zhangbei.rds.aliyuncs.com",
    "database": "xxx_release",
    "username": "root",
    "password": "xxx",
    "dialect": "mysql",
    "define": {
      "charset": "utf8"
    }
  },
  "production": {
    "port": 53306,
    "host": "rm-xxx.mysql.zhangbei.rds.aliyuncs.com",
    "database": "xxx_prd",
    "username": "root",
    "password": "xxx",
    "dialect": "mysql",
    "define": {
      "charset": "utf8"
    }
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "egg-sequelize-doc-unittest",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

database/umzug-seed.ts

import { Umzug, SequelizeStorage } from 'umzug';
// eslint-disable-next-line node/no-unpublished-import
import { Sequelize } from 'sequelize';
// config 加载
import config from './config.json';
import { get, snakeCase, replace } from 'lodash';
import path from 'path';
import fs from 'fs';

const rtlEnv = process.env.NODE_ENV;
const sequelizeConfig: any = get(config, rtlEnv || 'development');
console.log(`[umzug]:db:${sequelizeConfig.database}`);
const sequelize = new Sequelize(sequelizeConfig);

/**
 * 默认模版替换
 * @param filepath 路径
 * @returns
 */
const findTemplate = (filepath: string) => {
  const temp = fs
    .readFileSync(path.join('database/template/seed.ts'))
    .toString();
  const names = filepath.split('.');
  const name = snakeCase(names[names.length - 2]);
  return replace(temp, /\[tableName\]/g, name);
};

export const migrator = new Umzug({
  migrations: {
    glob: ['seeds/*.ts', { cwd: __dirname }],
  },
  create: {
    template: filepath => [[filepath, findTemplate(filepath)]],
    folder: path.join('database/seeds/'),
  },
  context: sequelize,
  storage: new SequelizeStorage({
    sequelize,
    modelName: 'SequelizeData',
  }),
  logger: console,
});

export type Migration = typeof migrator._types.migration;

databse/umzug.ts

import { Umzug, SequelizeStorage } from 'umzug';
// eslint-disable-next-line node/no-unpublished-import
import { Sequelize } from 'sequelize';
// config 加载
import config from './config.json';
import { get, snakeCase, replace } from 'lodash';
import path from 'path';
import fs from 'fs';

const rtlEnv = process.env.NODE_ENV;
const sequelizeConfig: any = get(config, rtlEnv || 'development');
console.log(`[umzug]:db:${sequelizeConfig.database}`);
const sequelize = new Sequelize(sequelizeConfig);

/**
 * 默认模版替换
 * @param filepath 路径
 * @returns
 */
const findTemplate = (filepath: string) => {
  const temp = fs
    .readFileSync(path.join('database/template/table.ts'))
    .toString();
  const names = filepath.split('.');
  const name = snakeCase(names[names.length - 2]);
  return replace(temp, /\[tableName\]/g, name);
};

export const migrator = new Umzug({
  migrations: {
    glob: ['migrations/*.ts', { cwd: __dirname }],
  },
  create: {
    template: filepath => [[filepath, findTemplate(filepath)]],
    folder: path.join('database/migrations/'),
  },
  context: sequelize,
  storage: new SequelizeStorage({
    sequelize,
  }),
  logger: console,
});

export type Migration = typeof migrator._types.migration;

database/utils/default-columns.ts

// eslint-disable-next-line node/no-unpublished-import
import Sequelize from 'sequelize';

const { DATE, STRING, INTEGER } = Sequelize;

export default {
  id: { type: STRING(50), primaryKey: true },
  // Creating two objects with the same value will throw an error. The unique property can be either a
  // boolean, or a string. If you provide the same string for multiple columns, they will form a
  created_at: {
    type: DATE,
    defaultValue: Sequelize.fn('now'),
    comment: '创建时间',
  },
  created_id: {
    type: STRING(50),
    defaultValue: '',
    comment: '创建人id',
  },
  updated_at: {
    type: DATE,
    defaultValue: Sequelize.fn('now'),
    comment: '修改时间',
  },
  updated_id: {
    type: STRING(50),
    comment: '修改人id',
  },
  deleted_at: { type: DATE, comment: '删除时间' },
  deleted_id: {
    type: STRING(50),
    comment: '删除人id',
  },
  business_code: {
    type: STRING(500),
    comment: '业务编码权限用',
  },
  remark: {
    type: STRING(500),
    comment: '备注',
  },
  version: {
    type: INTEGER,
    comment: 'BaseTable.version',
  },
  enable_flag: {
    type: INTEGER,
    comment: '状态 1启用 0停用默认1',
    defaultValue: 1,
  },
};

export const references = (tableName: string, keyName = 'id') => {
  if (process.env.NODE_ENV === 'production') {
    return undefined;
  }
  return {
    model: {
      tableName,
    },
    keyName,
  };
};

database/template/seed.ts

/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable node/no-unpublished-import */
import { MigrationFn } from 'umzug';
import { Sequelize } from 'sequelize/types/lib/sequelize';
// import { DataTypes } from 'sequelize';

export const up: MigrationFn<Sequelize> = async ({ context: sequelize }) => {
  return await sequelize.getQueryInterface().bulkInsert('[tableName]', [{}]);
};

export const down: MigrationFn<Sequelize> = async ({ context: sequelize }) => {
  return await sequelize.getQueryInterface().bulkDelete('[tableName]', {
    where: {
      id: [],
    },
  });
};

database/template/table.ts

/* eslint-disable @typescript-eslint/no-unused-vars */
/* eslint-disable node/no-unpublished-import */
import { MigrationFn } from 'umzug';
import { Sequelize } from 'sequelize/types/lib/sequelize';
// import { DataTypes } from 'sequelize';
import defaultCloumns from '../utils/default-cloumns';

export const up: MigrationFn<Sequelize> = async ({ context: sequelize }) => {
  return await sequelize.getQueryInterface().createTable('[tableName]', {
    ...defaultCloumns,
  });
};

export const down: MigrationFn<Sequelize> = async ({ context: sequelize }) => {
  return await sequelize.getQueryInterface().dropTable('[tableName]');
};

database/migrations -- model first
database/seeds -- 种子迁移

相关文章

网友评论

      本文标题:umzug sequelize 数据迁移方案 by midway

      本文链接:https://www.haomeiwen.com/subject/khriqrtx.html