这是我参与2022首次更文挑战的第10天,活动详情查看:2022首次更文挑战
作用域
作用域用于帮助复用用代码. 可以定义常用查询,并指定参数如 where, include, limit 等.
定义
作用域在模型定义中定义,可以是查找器对象,也可以是返回查找器对象的函数 - 默认作用域除外, 该作用域只能是一个对象:
class Project extends Model {}
Project.init({
// 属性
}, {
defaultScope: {
where: {
active: true
}
},
scopes: {
deleted: {
where: {
deleted: true
}
},
activeUsers: {
include: [
{ model: User, where: { active: true } }
]
},
random() {
return {
where: {
someNumber: Math.random()
}
}
},
accessLevel(value) {
return {
where: {
accessLevel: {
[Op.gte]: value
}
}
}
}
sequelize,
modelName: 'project'
}
});
可以在定义模型后通过调用 YourModel.addScope添加作用域,其中在定义另一个模型时可能未定义包含中的模型.
始终应用默认作用域, 使用上面的模型定义,Project.findAll() 将创建以下查询:
SELECT * FROM projects WHERE active = true
可以通过调用 .unscoped(), .scope(null), 或调用另一个作用域来删除默认作用域:
await Project.scope('deleted').findAll(); // 删除默认作用域
SELECT * FROM projects WHERE deleted = true
也可以在作用域定义中包括作用域模型. 这样可以避免重复 include, attributes 或 where 定义. 使用上面的示例,并在包含的用户模型上调用 active 作用域(而不是直接在该包含对象中指定条件):
// 上例中定义的 `activeUsers` 作用域也可以通过以下方式定义:
Project.addScope('activeUsers', {
include: [
{ model: User.scope('active') }
]
});
使用
通过在模型定义上调用 .scope,并传递一个或多个作用域的名称来应用作用域..scope 返回具有所有常规方法的功能齐全的模型实例:.findAll, .update, .count, .destroy 等, 模型实例并复用
const DeletedProjects = Project.scope('deleted');
await DeletedProjects.findAll();
// 以上相当于:
await Project.findAll({
where: {
deleted: true
}
});
作用域适用于 .find, .findAll, .count, .update, .increment 和 .destroy
作用域可以通过两种方式调用, 如果作用域不带任何参数,则可以正常调用它, 如果作用域接受参数,则传递一个对象:
await Project.scope('random', { method: ['accessLevel', 19] }).findAll();
// 生成SQL
SELECT * FROM projects WHERE someNumber = 42 AND accessLevel >= 19
合并
通过将作用域数组传递给 .scope 或将作用域作为连续参数传递,可以同时应用多个作用域.
// 这两个是等效的
await Project.scope('deleted', 'activeUsers').findAll();
await Project.scope(['deleted', 'activeUsers']).findAll();
如果要在默认作用域之外应用另一个作用域,将关键字 defaultScope 传递给.scope:=
await Project.scope('defaultScope', 'deleted').findAll();
调用多个合并作用域时,后续合并作用域中的键将覆盖先前合并作用域中的键(类似于 Object.assign ,除了将合并的 where 和 include 之外. 考虑两个作用域:
YourMode.addScope('scope1', {
where: {
firstName: 'bob',
age: {
[Op.gt]: 20
}
},
limit: 2
});
YourMode.addScope('scope2', {
where: {
age: {
[Op.gt]: 30
}
},
limit: 10
});