sequelize
常见用法
建表设置某个字段独一无二
unique: true
username: {
type: DataTypes.STRING,
allowNull: false,
comment: '用户名',
unique: true
},
查询表中某个字段不重复的所有数据
await Model.findAll({
attributes: [[sequelize.fn('DISTINCT', sequelize.col('col_name')), 'alias']],
})
批量删除
await Model.destroy({
where: {
id: {
[Op.in]: ids
}
}
})
分页、排序、模糊查询搜索、查询状态
Menu
表自身与自身关联
Menu.hasMany(Menu, { as: 'children', foreignKey: 'pid', through: null })
自身与自身关联多条件查询
// 查询(分页、排序、模糊查询搜索、查询状态)
/**
* limit 提取多少行,offset 跳过多少行
* @param {*} page 当前页码
* @param {*} size 每页条数
*/
async function findAll (query) {
try {
const size = query.size ? parseInt(query.size) : 10 // 如果没传参数设置一个默认值
const page = query.page ? parseInt(query.page) : 1
const { count, rows } = await Menu.findAndCountAll({
include: {
model: Menu,
as: 'children',
include: {
model: Menu,
as: 'children',
include: {
model: Menu,
as: 'children',
include: {
model: Menu,
as: 'children'
}
}
}
},
where: {
pid: null,
status: {
[Op.like]: query.status ? `%${JSON.parse(query.status) ? 1 : 0}%` : '%%' // 查询状态
},
[Op.or]: [ // 模糊查询
{ name: { [Op.like]: query.search ? `%${query.search}%` : '%%' } },
{ icon: { [Op.like]: query.search ? `%${query.search}%` : '%%' } },
{ component: { [Op.like]: query.search ? `%${query.search}%` : '%%' } },
{ type: { [Op.like]: query.search ? `%${query.search}%` : '%%' } },
{ remark: { [Op.like]: query.search ? `%${query.search}%` : '%%' } },
{ ctime: { [Op.like]: query.search ? `%${query.search}%` : '%%' } },
{ mtime: { [Op.like]: query.search ? `%${query.search}%` : '%%' } }
],
},
offset: (page - 1) * size,
limit: size,
distinct: true, // 避免分页出的总数和实际数不匹配
order: [
[query.order ? query.order : 'ctime', query.sort ? query.sort : 'desc'] // 使用 Element 表格中的排序是互斥的,所以每次排序只能排一个元素的
]
})
return {
count,
data: rows
}
} catch (error) {
throw error
}
}
一对多关联
Permission.belongsTo(Tag, { as: 'tid', foreignKey: 'tag', through: null }) // Permission -> Tag: 一对多
一对多关联查询
await Permission.findAndCountAll({
include: [{
model: Tag,
as: 'tid',
attributes: ['id', 'name'],
}], // 关联查询
})
多对多关联
Role.belongsToMany(Menu, { through: 'role_menu', as: 'role_menu' })
Menu.belongsToMany(Role, { through: 'role_menu', as: 'role_menu' })
可能添加 as
报别名重复的错误,可以不使用 as
会创建一个名为 role_menu
的中间表,里面包含了 role
和 menu
表的外键
多对多关联查询
await Role.findAndCountAll({
include: [{
model: Menu,
as: 'menus',
attributes: ['id', 'name'],
through: { attributes: [] } // 隐藏中间表字段
}]
}
多对多中间表的操作
以 role_menu
中间表为例
sequelize
提供了 addMenus()
和 setMenus()
等方法可以对中间表增删改查的操作
async function setRoleMenu (data) {
try {
const role = await Role.findOne({ // 找到对应的 role 对象
where: { id: data['roleId'] }
})
const menus = await Menu.findAll({ // 找到对应的 menuIds的对象
where: { id: data['menuIds'] }
})
return await role.setMenus(menus) // 通过 setMenus 方法在 role_menu 表中添加/修改记录
} catch (error) {
throw error
}
}