yarn add sequelize
yarn add sequelize-cli
yarn add mysql2
.\node_modules\.bin\sequelize
.\node_modules\.bin\sequelize init
# 生成对应的文件夹
# config 配置文件夹
# migrations 迁移文件夹
# models 模型文件夹
# seeders 种子文件夹
// config -> config.json
// 三种开发环境的, 只是取一种, 开发环境
"development": {
"username": "root",
"password": "root",
"database": "sequelize_db",
"host": "127.0.0.1",
"dialect": "mysql",
"operatorsAliases": false // 删除这一行, 上一行的逗号也去掉
},
# 设置数据库默认编码为utf8
.\node_modules\.bin\sequelize db:create --charset 'utf8'
.\node_modules\.bin\sequelize db:drop
# create 和 generate 都可以
# 如果表的字段很多的话, 那么命令行就写一两个, 后面可以在文件里面更改
.\node_modules\.bin\sequelize model:create --name User --attributes username:string,password:string
.\node_modules\.bin\sequelize db:migrate
# 撤销上一次迁移
.\node_modules\.bin\sequelize db:migrate:undo
# 撤销指定迁移
.\node_modules\.bin\sequelize db:migrate:undo --name xxx
# 撤销所有迁移
.\node_modules\.bin\sequelize db:migrate:undo:all
.\node_modules\.bin\sequelize seed:create --name users-seed
// down 也要有
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
const usersArr = [];
for (let i = 2; i <= 10; i++) {
usersArr.push({
username: `user${i}`,
password: `user${i}`,
email: `user${i}@qq.com`
})
}
// users => 表名
return queryInterface.bulkInsert('users', usersArr, {});
},
down: (queryInterface, Sequelize) => {
return queryInterface.bulkDelete('users', null, {});
}
};
# 如果运行过一次, 再次运行就会报错, 除非删除上一次填充的种子文件
.\node_modules\.bin\sequelize db:seed:all # 也可以指定文件命令和迁移命令类似
参考网站
// 迁移文件
Sequelize.STRING // varchar(255)
Sequelize.STRING(50)
Sequelize.INTEGER
Sequelize.TEXT
Sequelize.BIGINT
Sequelize.BIGINT(11)
Sequelize.FLOAT // FLOAT
Sequelize.FLOAT(11) // FLOAT(11)
Sequelize.FLOAT(11, 10) // FLOAT(11,10)
Sequelize.DOUBLE // DOUBLE
Sequelize.DOUBLE(11) // DOUBLE(11)
Sequelize.DOUBLE(11, 10) // DOUBLE(11,10)
Sequelize.DECIMAL // DECIMAL
Sequelize.DECIMAL(10, 2) // DECIMAL(10,2)
Sequelize.DATE // DATETIME for mysql / sqlite, TIMESTAMP WITH TIME ZONE for postgres
Sequelize.DATE(6) // DATETIME(6) for mysql 5.6.4+. Fractional seconds support with up to 6 digits of precision
Sequelize.DATEONLY // DATE without time.
Sequelize.BOOLEAN // TINYINT(1)
Sequelize.ENUM('value 1', 'value 2') // An ENUM with allowed values 'value 1' and 'value 2'
Sequelize.JSON // JSON column. PostgreSQL, SQLite and MySQL only.
官方网站
// 迁移文件 设计数据表的
{
allowNull: false, // 是否允许为空
autoIncrement: true, // 字段是否是自增类型
primaryKey: true, // 字段是否是主键
type: Sequelize.INTEGER // 字段是整型
defaultValue: null, // 字段默认值
unique: true // 唯一索引
}
// 迁移文件, 也可以在这里添加唯一索引
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Users', {
}).then(()=>{
// ===================普通索引=======================================
return queryInterface.addIndex('users', ['email'])
// ===================普通索引=======================================
/* return queryInterface.addIndex('users', {
name: 'email-index',
fields: ['email']
}) */
// =======================唯一索引====================================
/* return queryInterface.addIndex('users', ['username'], {
unique: true
}) */
// ========================唯一索引====================================
/* return queryInterface.addIndex('users', {
name: 'username',
unique: true,
fields: ['username']
}); */
});
},
参考网站
'use strict';
module.exports = {
up: (queryInterface, Sequelize) => {
return queryInterface.createTable('Articles', {
id: {
allowNull: false,
autoIncrement: true,
primaryKey: true,
type: Sequelize.INTEGER
},
title: {
type: Sequelize.STRING
},
authorid: {
type: Sequelize.INTEGER,
// 第一种方法
/* references: {
model: {
tableName: 'users'
},
key: 'id',
} */
}
}).then(() => {
// 填充测试数据时候, 有外键约束就会报错, 除非把外键字段一起填充
return queryInterface.addConstraint('articles', ['authorid'], {
type: 'foreign key',
name: 'article-constraint',
references: {
table: 'users',
field: 'id'
},
// Mysql外键约束之CASCADE、SET NULL、RESTRICT、NO ACTION
// What should happen when the referenced key is updated. One of CASCADE, RESTRICT, SET DEFAULT, SET NULL or NO ACTION
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
});
},
down: (queryInterface, Sequelize) => {
return queryInterface.dropTable('Articles');
}
};
// user模型
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
username: DataTypes.STRING,
password: DataTypes.STRING,
email: DataTypes.STRING
}, {
timestamps: false
});
User.associate = function (models) {
// associations can be defined here
models.User.hasMany(models.Article, {
as: 'articles',
foreignKey: 'authorid',
sourceKey: 'id'
})
};
return User;
};
// article模型
'use strict';
module.exports = (sequelize, DataTypes) => {
const Article = sequelize.define('Article', {
title: DataTypes.STRING,
content: DataTypes.TEXT,
hit: DataTypes.INTEGER,
authorid: {
type: DataTypes.INTEGER,
async get() {
const aid = this.getDataValue('authorid')
const user = await sequelize.model('User').findByPk(aid)
console.log(user.dataValues.username);
}
},
createdAt: DataTypes.DATE,
updatedAt: DataTypes.DATE
}, {});
Article.associate = function (models) {
// associations can be defined here
models.Article.belongsTo(models.User, {
// 主表删除的时候从表记录也跟着删除, 如果是NUll那么就用NULL填充(条件: 这个字段允许为NULL)
onDelete: 'CASCADE',
as: 'user',
foreignKey: 'authorid',
/* foreignKey: {
fieldName: 'userId',
allowNull: false
}, */
targetKey: 'id'
})
};
return Article;
};
// get
publish: {
/*
type: DataTypes.ENUM,
values: ['happy', 'sad', 'neutral']
*/
type: DataTypes.ENUM('0', '1'),
get() {
const p = this.getDataValue('publish')
return p == 0 ? '未发表' : '发表'
}
}
// set
token: {
type: DataTypes.STRING,
set(val) {
return this.setDataValue('token', `chenjiang${val}`.toUpperCase())
}
}
参考网站
const models = require('../models/index');
// 通过主键获取数据
const user = await models.User.findByPk(1)
// 获取所有数据
const users = await models.User.findAll()
// 获取所有数据并统计条数
const users = await models.User.findAndCountAll()
// 获取模型关联的数据
const users = await models.User.findAll({
include: [{
model: models.Article,
as: 'articles',
where: {
hit: {
[Op.lt]: 10
}
}
}]
})
// 获取一条数据(指定条件)
const user = await models.User.findOne({
where: {
'username': 'user4'
}
})
// 获取数据如果没有就创建
const user = await models.User.findOrCreate({
where: {
username: 'user101'
},
defaults:{
username: 'user101',
password: 'user101',
email: '[email protected]'
}
})
// 创建数据
const user = await models.User.create({
username: 'user102',
password: 'user102',
email: '[email protected]'
})
// 批量创建数据
const usersArr = []
for (let i = 20; i < 30; i++) {
usersArr.push({
username: `user${i}`,
password: `user${i}`,
email: `user${i}@qq.com`
})
}
const users = await models.User.bulkCreate(usersArr)
// 更新数据
const user = await models.User.findOne({
where: {
username: 'user3'
}
})
user.update({
username: 'userupdate'
})
// 更新数据
const user = await models.User.update({
'username': 'gooduser'
}, {
where: {
'username': 'user4'
}
})
const article = await models.Article.findByPk(3)
// 自增
const result = await article.increment('hit')
// 自减
const result = await article.decrement('hit')
// 删除数据
const user = await models.User.findByPk(2)
user.destroy()
// 删除数据
const user = await models.User.destroy({
where: {
'username': 'user3'
}
})
// 引入Op模块
const models = require('../models/index')
const Op = models.Sequelize.Op // 大写Sequelize
Project.findAll({
where: {
id: {
[Op.and]: {a: 5}, // AND (a = 5)
[Op.or]: [{a: 5}, {a: 6}], // (a = 5 OR 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.between]: [6, 10], // BETWEEN 6 AND 10
[Op.notBetween]: [11, 15], // NOT BETWEEN 11 AND 15
[Op.in]: [1, 2], // IN [1, 2]
[Op.notIn]: [1, 2], // NOT IN [1, 2]
[Op.like]: '%hat', // LIKE '%hat'
[Op.notLike]: '%hat', // NOT LIKE '%hat'
[Op.iLike]: '%hat', // ILIKE '%hat' (case insensitive) (PG only)
[Op.notILike]: '%hat', // NOT ILIKE '%hat' (PG only)
[Op.overlap]: [1, 2], // && [1, 2] (PG array overlap operator)
[Op.contains]: [1, 2], // @> [1, 2] (PG array contains operator)
[Op.contained]: [1, 2], // <@ [1, 2] (PG array contained by operator)
[Op.any]: [2,3] // ANY ARRAY[2, 3]::INTEGER (PG only)
},
status: {
[Op.not]: false // status NOT FALSE
}
}
}
Project.findOne({
where: {
name: 'a project',
[Op.or]: [
{ id: [1,2,3] },
{ id: { [Op.gt]: 10 } }
]
}
})
Project.findOne({
where: {
name: 'a project',
id: {
[Op.or]: [
[1,2,3],
{ [Op.gt]: 10 }
]
}
}
})
const user = await models.User.findAll({
offset: 2, // 跳过两条, 然后再读取
limit: 2, // 获取数量,
})
const user = await models.User.findAll({
order: [
['id', 'desc'] // 按id, 倒序
]
})
const user = await models.Article.findAll({
group: 'authorid'
})
const users = await models.User.findAll({
where: {
'username': 'user2'
},
attributes: ['id', 'username', 'email', ['token', 'token别名']]
//SELECT token AS token别名
})
// 排除一些字段
const user = await models.User.findAll({
attributes: {
exclude: ['password']
}
})
'use strict';
module.exports = (sequelize, DataTypes) => {
const User = sequelize.define('User', {
username: DataTypes.STRING,
password: DataTypes.STRING
}, {});
User.associate = function (models) {
// associations can be defined here
models.User.hasMany(models.Article, {
as: 'articles', // 在读取数据时候include 里面也要同时指定 as: 'articles'
foreignKey: 'authorid',
sourceKey: 'id' // 默认是id可以省略不写
})
};
return User;
};
// 获取数据
const users = await models.User.findAll({
include: [{
model: models.Article,
as: 'articles',
}],
})
'use strict';
module.exports = (sequelize, DataTypes) => {
const Article = sequelize.define('Article', {
title: DataTypes.STRING
}, {});
Article.associate = function (models) {
// associations can be defined here
models.Article.belongsTo(models.User, {
// 主表删除的时候从表记录也跟着删除, 如果是NUll那么就用NULL填充(条件: 这个字段允许为NULL)
onDelete: 'CASCADE'
as: 'user', // 在读取数据时候include 里面也要同时指定 as: 'user'
foreignKey: 'authorid',
/* foreignKey: {
fieldName: 'authorid',
allowNull: false
}, */
targetKey: 'id' // 默认是id可以省略不写
})
};
return Article;
};
// 获取数据
const articles = await models.Article.findAll({
include: [{
model: models.User,
as: 'user',
}],
})
// 学生表
'use strict';
module.exports = (sequelize, DataTypes) => {
const Student = sequelize.define('Student', {
study_no: {
type: DataTypes.STRING,
primaryKey: true
},
name: DataTypes.STRING
}, {
timestamps: false
});
Student.associate = function (models) {
// associations can be defined here
Student.belongsToMany(models.Course, {
as: 'courses',
through: models.Student_Course,
foreignKey: 's_id'
})
};
return Student;
};
// 课程表
'use strict';
module.exports = (sequelize, DataTypes) => {
const Course = sequelize.define('Course', {
name: DataTypes.STRING
}, {
timestamps: false
});
Course.associate = function (models) {
// associations can be defined here
Course.belongsToMany(models.Student, {
through: models.Student_Course,
foreignKey: 'c_id'
})
};
return Course;
};
// 中间表
'use strict';
module.exports = (sequelize, DataTypes) => {
const Student_Course = sequelize.define('Student_Course', {
s_id: DataTypes.STRING,
c_id: DataTypes.INTEGER
}, {
timestamps: false
});
Student_Course.associate = function (models) {
// associations can be defined here
};
return Student_Course;
};
// 获取数据
const students = await models.Student.findAll({
include: [{
model: models.Course,
as: 'courses',
through: { // 除去中间表
attributes: []
}
}],
})
router.get('/posts/:page/:limit', async (req, res) => {
// let {name = 1} = {name: 'undefined'} //undefined
let {
page = 1, limit = 5
} = req.params
let offset = (Number(page) - 1) * limit
const posts = await models.Post.findAndCountAll({
attributes: {
exclude: ['updatedAt', 'createdAt']
},
offset,
limit: Number(limit),
order: [
['id', 'desc']
]
})
return res.status(200).json(posts)
})
// vue element-ui
export default {
name: "app",
data() {
return {
posts: [],
page: {
limit: 5,
page: 1,
total: 0,
size: 5
}
};
},
methods: {
fetch() {
this.$http
.get(`posts/${this.page.page}/${this.page.limit}`)
.then(res => {
this.posts = res.data.rows;
this.page.total = res.data.count;
});
},
handleSizeChange(val) {
this.page.limit = val;
this.fetch();
},
handleCurrentChange(val) {
this.page.page = val;
this.fetch();
}
},
created() {
this.fetch();
}
};