关联
Sequelize 与关联有两个不同但相关的作用域概念. 差异是微妙但重要的:
- 关联作用域 允许你在获取和设置关联时指定默认属性 - 在实现多态关联时很有用. 当使用
get
,set
,add
和create
相关联的模型函数时,这个作用域仅在两个模型之间的关联上被调用 - 关联模型上的作用域 允许你在获取关联时应用默认和其他作用域,并允许你在创建关联时传递作用域模型. 这些作用域都适用于模型上的常规查找和通过关联查找.
举个例子,思考模型Post和Comment. Comment与其他几个模型(图像,视频等)相关联,Comment和其他模型之间的关联是多态的,这意味着除了外键 commentable_id
之外,注释还存储一个commentable
列.
可以使用 association scope 来实现多态关联:
this.Post.hasMany(this.Comment, {
foreignKey: 'commentable_id',
scope: {
commentable: 'post'
}
});
当调用 post.getComments()
时,这将自动添加 WHERE commentable = 'post'
. 类似地,当向帖子添加新的注释时,commentable
会自动设置为 'post'
. 关联作用域是为了存活于后台,没有程序员不必担心 - 它不能被禁用. 有关更完整的多态性示例,请参阅 关联作用域
那么考虑那个Post的默认作用域只显示活动的帖子:where: { active: true }
. 该作用域存在于相关联的模型(Post)上,而不是像commentable
作用域那样在关联上. 就像在调用Post.findAll()
时一样应用默认作用域,当调用 User.getPosts()
时,它也会被应用 - 这只会返回该用户的活动帖子.
要禁用默认作用域,将 scope: null
传递给 getter: User.getPosts({ scope: null })
. 同样,如果要应用其他作用域,请像这样:
User.getPosts({ scope: ['scope1', 'scope2']});
如果要为关联模型上的作用域创建快捷方式,可以将作用域模型传递给关联. 考虑一个快捷方式来获取用户所有已删除的帖子:
class Post extends Model {}
Post.init(attributes, {
defaultScope: {
where: {
active: true
}
},
scopes: {
deleted: {
where: {
deleted: true
}
}
},
sequelize,
});
User.hasMany(Post); // 常规 getPosts 关联
User.hasMany(Post.scope('deleted'), { as: 'deletedPosts' });
User.getPosts(); // WHERE active = true
User.getDeletedPosts(); // WHERE deleted = true