关联

Sequelize 与关联有两个不同但相关的作用域概念. 差异是微妙但重要的:

  • 关联作用域 允许你在获取和设置关联时指定默认属性 - 在实现多态关联时很有用. 当使用get,set,addcreate相关联的模型函数时,这个作用域仅在两个模型之间的关联上被调用
  • 关联模型上的作用域 允许你在获取关联时应用默认和其他作用域,并允许你在创建关联时传递作用域模型. 这些作用域都适用于模型上的常规查找和通过关联查找.

举个例子,思考模型Post和Comment. Comment与其他几个模型(图像,视频等)相关联,Comment和其他模型之间的关联是多态的,这意味着除了外键 commentable_id 之外,注释还存储一个commentable列.

可以使用 association scope 来实现多态关联:

  1. this.Post.hasMany(this.Comment, {
  2. foreignKey: 'commentable_id',
  3. scope: {
  4. commentable: 'post'
  5. }
  6. });

当调用 post.getComments() 时,这将自动添加 WHERE commentable = 'post'. 类似地,当向帖子添加新的注释时,commentable 会自动设置为 'post'. 关联作用域是为了存活于后台,没有程序员不必担心 - 它不能被禁用. 有关更完整的多态性示例,请参阅 关联作用域

那么考虑那个Post的默认作用域只显示活动的帖子:where: { active: true }. 该作用域存在于相关联的模型(Post)上,而不是像commentable 作用域那样在关联上. 就像在调用Post.findAll() 时一样应用默认作用域,当调用 User.getPosts() 时,它也会被应用 - 这只会返回该用户的活动帖子.

要禁用默认作用域,将 scope: null 传递给 getter: User.getPosts({ scope: null }). 同样,如果要应用其他作用域,请像这样:

  1. User.getPosts({ scope: ['scope1', 'scope2']});

如果要为关联模型上的作用域创建快捷方式,可以将作用域模型传递给关联. 考虑一个快捷方式来获取用户所有已删除的帖子:

  1. class Post extends Model {}
  2. Post.init(attributes, {
  3. defaultScope: {
  4. where: {
  5. active: true
  6. }
  7. },
  8. scopes: {
  9. deleted: {
  10. where: {
  11. deleted: true
  12. }
  13. }
  14. },
  15. sequelize,
  16. });
  17. User.hasMany(Post); // 常规 getPosts 关联
  18. User.hasMany(Post.scope('deleted'), { as: 'deletedPosts' });
  1. User.getPosts(); // WHERE active = true
  2. User.getDeletedPosts(); // WHERE deleted = true