Sequelize
MySQL
model
'use strict';
const moment = require('moment');// 日期处理模块
module.exports = app => {
const Instance = app.model.define('test', {
id: {
/**
* ! 数据类型
* ?
* STRING 字符串
*
* DOUBLE 0 1 double
*
* *&*********日期
* DATE DATETIME 适用于 mysql / sqlite, 带时区的TIMESTAMP 适用于 postgres
* DATE(6) DATETIME(6) 适用于 mysql 5.6.4+. 支持6位精度的小数秒
* DATEONLY 不带时间的 DATE
*
* *&*********数字
* INTEGER integer
* FLOAT float
* REAL real
* DOUBLE double
*
*/
type: app.Sequelize.INTEGER(5),
primaryKey: true, // 住建
autoIncrement: true, // 自增
unique: true, // 唯一
allowNull: true, // 不允许为空
description: '唯一标识', // 描述
defaultValue: 10000, // 默认值
// comment: '这是带有注释的列', //额外的注释
},
// 日期的默认值 => 当前时间
// myDate: { type: DataTypes.DATE, defaultValue: DataTypes.NOW },
// 创建时间 修改时间 格式化
createdAt: { type: app.Sequelize.DATE, get() { return moment(this.getDataValue('created_at')).format('YYYY-MM-DD HH:mm:ss'); } },
updatedAt: { type: app.Sequelize.DATE, get() { return moment(this.getDataValue('updated_at')).format('YYYY-MM-DD HH:mm:ss'); } },
}, {
// comment: '实例', // 表注释
// modelName: 'tablename', // 定义表名
// 在上面的属性中使用 `unique: true` 与在模型的参数中创建索引完全相同:
indexes: [
{
unique: true,
fields: [ 'id' ], // 唯一约束
},
],
});
// 外键约束
Instance.associate = function() {
// 一对一
// app.model.Stores.Type.belongsTo(app.model.Managers.User, { foreignKey: 'author', targetKey: 'id' });
// 一对多
// app.model.Answer.Content.hasMany(app.model.Answer.Options, { foreignKey: 'answerId', targetKey: 'id' });
// app.model.Answer.Options.belongsTo(app.model.Answer.Content, { foreignKey: 'answerId', targetKey: 'id' });
};
return Instance;
};
controller
'use strict';
const Controller = require('egg').Controller;
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
// 全局变量
const tableName = 'TableName';
// 数据库模块 名称
const models = {
modelGroup: 'ModelGroup',
modelName: 'ModelName',
};
// 定义创建接口的请求参数规则
const createRule = {
// username: {
// type: 'userName', // type -属性的类型,每种类型都有自己的验证规则。
// 如果required设置为false,则此属性可以为null或未定义。默认为true
// convertType-使参数转换的输入参数的具体类型,支持int,number,string和boolean,还支持功能,定制自己的转换方法。
// default-属性的默认值,一旦允许该属性为非必需和丢失的,则参数将使用该默认值。这可能会更改原始的输入参数。
// },
};
// 定义修改接口的请求参数规则
const updateRule = {
// id: { type: 'Id' },
};
class TestController extends Controller {
/**
* @description 查询数据
*/
async index() {
// 分页参数
const pagedata = {
page: this.ctx.query.page,
limit: this.ctx.query.rows,
};
const pageNumber = this.ctx.helper.pageNumber(pagedata);
const search = this.ctx.query.search || ''; // 搜索内容
const find = await this.ctx.service.database.query.findAndCountAll({
...models,
// 查询条件
conditions: {
...pageNumber,
attributes: {
// 排除 查询字段
exclude: [ 'updated_at', 'deleted_at', 'created_at' ],
include: [
// 字段 修改名称
[ Sequelize.col('created_at'), 'createdTime' ],
],
},
order: [ // id倒叙
[ 'id', 'DESC' ],
],
include: [
// 关联 表
],
// 查询 条件
// WHERE
where: {
name: { // TODO
[Op.like]: `%${search}%`,
// [Op.and]: {a: 5} // 且 (a = 5)
// [Op.or]: [{a: 5}, {a: 6}] // (a = 5 或 a = 6)
// [Op.gt]: 6, // id > 6
// [Op.gte]: 6, // id >= 6
// [Op.lt]: 10, // id < 10
// [Op.lte]: 10, // id <= 10
// [Op.ne]: 20, // id != 20
// [Op.eq]: 3, // = 3
// [Op.not]: true, // 不是 TRUE
// [Op.between]: [6, 10], // 在 6 和 10 之间
// [Op.notBetween]: [11, 15], // 不在 11 和 15 之间
// [Op.in]: [1, 2], // 在 [1, 2] 之中
// [Op.notIn]: [1, 2], // 不在 [1, 2] 之中
// [Op.like]: '%hat', // 包含 '%hat'
// [Op.notLike]: '%hat' // 不包含 '%hat'
// [Op.iLike]: '%hat' // 包含 '%hat' (不区分大小写) (仅限 PG)
// [Op.notILike]: '%hat' // 不包含 '%hat' (仅限 PG)
// [Op.startsWith]: 'hat' // 类似 'hat%'
// [Op.endsWith]: 'hat' // 类似 '%hat'
// [Op.substring]: 'hat' // 类似 '%hat%'
// [Op.regexp]: '^[h|a|t]' // 匹配正则表达式/~ '^[h|a|t]' (仅限 MySQL/PG)
// [Op.notRegexp]: '^[h|a|t]' // 不匹配正则表达式/!~ '^[h|a|t]' (仅限 MySQL/PG)
// [Op.iRegexp]: '^[h|a|t]' // ~* '^[h|a|t]' (仅限 PG)
// [Op.notIRegexp]: '^[h|a|t]' // !~* '^[h|a|t]' (仅限 PG)
// [Op.like]: { [Op.any]: ['cat', 'hat']} // 包含任何数组['cat', 'hat'] - 同样适用于 iLike 和 notLike
// [Op.overlap]: [1, 2] // && [1, 2] (PG数组重叠运算符)
// [Op.contains]: [1, 2] // @> [1, 2] (PG数组包含运算符)
// [Op.contained]: [1, 2] // <@ [1, 2] (PG数组包含于运算符)
// [Op.any]: [2,3] // 任何数组[2, 3]::INTEGER (仅限PG)
// [Op.col]: 'user.organization_id' // = 'user'.'organization_id', 使用数据库语言特定的列标识符, 本例使用 PG
},
},
},
});
this.ctx.body = await this.ctx.helper.outputJSON({ data: { ...find }, msg: `${tableName}信息成功` });
}
/**
* @description 创建数据
*/
async create() {
const data = this.ctx.request.body;
data.author = await this.ctx.managers.id;
this.ctx.validate(createRule, this.ctx.request.body);
const creat = await this.ctx.service.database.create.create({
...models,
data,
});
this.ctx.body = await this.ctx.helper.outputJSON({ data: creat, msg: `${tableName}创建成功` });
}
/**
* @description 更新数据
*/
async update() {
try {
this.ctx.validate(updateRule, this.ctx.request.body);
const retdata = await this.ctx.service.database.update.update({
...models,
data: {
// TODO 修改字段
// TODO UPDATA
// name: this.ctx.request.body.name,
},
id: this.ctx.helper.parseInt(this.ctx.params.id),
});
const res = retdata ? await this.ctx.helper.outputJSON({ msg: `${tableName}信息修改` }) : await this.ctx.helper.outputErrJSON({ msg: '没有找到修改的内容' });
this.ctx.body = await res;
return;
} catch (error) {
this.ctx.body = await this.ctx.helper.outputErrJSON({ msg: '出现错误' });
return;
}
}
/**
* @description 删除数据
*/
async destroy() {
const data = await this.ctx.service.database.query.findByPk({ id: this.ctx.helper.parseInt(this.ctx.params.id), ...models });
if (!data) {
this.ctx.body = await this.ctx.helper.outputErrJSON({ msg: '没有找到要删除的内容' });
return;
}
await this.service.database.destroy.destroy({ id: this.ctx.helper.parseInt(this.ctx.params.id), ...models });
this.ctx.body = await this.ctx.helper.outputJSON({ msg: `${tableName}已删除` });
}
}
module.exports = TestController;
sequelizerc
安装
npm install --save-dev sequelize-cli
配置
// .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
### 迁移
(文档)[https://github.com/demopark/sequelize-docs-Zh-CN/blob/v5/migrations.md]
1. 安装 sequelize-cli
npm install --save-dev sequelize-cli
2. .sequelizerc 配置文件
``` .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
config, 包含配置文件,它告诉CLI如何连接数据库
models,包含你的项目的所有模型
migrations, 包含所有迁移文件
seeders, 包含所有种子文件
- 将其改成我们项目中使用的数据库配置
"development": {
"username": "root",
"password": null,
"database": "egg-sequelize-doc-default", // 数据库
"host": "127.0.0.1", // 地址
"dialect": "mysql" // 数据库类型
},
- 此时 sequelize-cli 和相关的配置也都初始化好了,我们可以开始编写项目的第一个 Migration 文件来创建我们的一个 users 表了 npx sequelize migration:generate —name=init-users
npx sequelize migration:generate —name User —attributes firstName:string,lastName:string,email:string
如果你的数据库还不存在,你可以调用 db:create 命令. 通过正确的访问,它将为你创建该数据库.
- 添加字段
'use strict';
module.exports = {
// 在执行数据库升级时调用的函数,创建 users 表
up: async (queryInterface, Sequelize) => {
const { INTEGER, DATE, STRING } = Sequelize;
await queryInterface.createTable('users', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30),
age: INTEGER,
created_at: DATE,
updated_at: DATE,
});
},
// 在执行数据库降级时调用的函数,删除 users 表
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
8. 编写model
``` js
'use strict';
module.exports = app => {
const { STRING, INTEGER, DATE } = app.Sequelize;
const User = app.model.define('user', {
id: { type: INTEGER, primaryKey: true, autoIncrement: true },
name: STRING(30),
age: INTEGER,
created_at: DATE,
updated_at: DATE,
});
return User;
};
- 访问model
// app/controller/users.js
const Controller = require('egg').Controller;
function toInt(str) {
if (typeof str === 'number') return str;
if (!str) return str;
return parseInt(str, 10) || 0;
}
class UserController extends Controller {
async index() {
const ctx = this.ctx;
const query = { limit: toInt(ctx.query.limit), offset: toInt(ctx.query.offset) };
ctx.body = await ctx.model.User.findAll(query);
}
async show() {
const ctx = this.ctx;
ctx.body = await ctx.model.User.findByPk(toInt(ctx.params.id));
}
async create() {
const ctx = this.ctx;
const { name, age } = ctx.request.body;
const user = await ctx.model.User.create({ name, age });
ctx.status = 201;
ctx.body = user;
}
async update() {
const ctx = this.ctx;
const id = toInt(ctx.params.id);
const user = await ctx.model.User.findByPk(id);
if (!user) {
ctx.status = 404;
return;
}
const { name, age } = ctx.request.body;
await user.update({ name, age });
ctx.body = user;
}
async destroy() {
const ctx = this.ctx;
const id = toInt(ctx.params.id);
const user = await ctx.model.User.findByPk(id);
if (!user) {
ctx.status = 404;
return;
}
await user.destroy();
ctx.status = 200;
}
}
module.exports = UserController;
- 创建第一个种子
npx sequelize-cli seed:generate --name managers
# 同上
npx sequelize seed:generate --name managers
- 运行种子 撤销种子
# 运行种子
npx sequelize-cli db:seed:all
# 如果你想撤消最近的种子
npx sequelize-cli db:seed:undo
# 如果你想撤消特定的种子
npx sequelize-cli db:seed:undo --seed name-of-seed-as-in-data
# 如果你想撤消所有的种子
npx sequelize-cli db:seed:undo:all
下一个是具有外键的迁移示例. 你可以使用 references 来指定外键:
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Person', {
name: Sequelize.STRING,
isBetaMember: {
type: Sequelize.BOOLEAN,
defaultValue: false,
allowNull: false
},
userId: {
type: Sequelize.INTEGER,
references: {
model: {
tableName: 'users',
schema: 'schema'
}
key: 'id'
},
allowNull: false
},
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Person');
}
}
.sequelizerc 文件
这是一个特殊的配置文件. 它允许你指定通常作为参数传递给CLI的各种选项:
env: 在其中运行命令的环境 config: 配置文件的路径 options-path: 带有其他参数的 JSON 文件的路径 migrations-path: migrations 文件夹的路径 seeders-path: seeders 文件夹的路径 models-path: models 文件夹的路径 url: 要使用的数据库连接字符串. 替代使用 —config 文件 debug: 可用时显示各种调试信息
初始化项目
# 创建数据库
npx sequelize db:create
# 创建表
npx sequelize db:migrate
# 创建默认值
npx sequelize db:seed:all
数据回滚
# 如果你想撤消所有的种子
npx sequelize-cli db:seed:undo:all
# 回退到初始状态
npx sequelize db:migrate:undo:all
生成公钥:openssl genrsa -out rsa_private_key.pem 1024 生成私钥: openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
```