Sequelize嵌套的渴望加载找到所有嵌套关联不匹配的地方

Posted

技术标签:

【中文标题】Sequelize嵌套的渴望加载找到所有嵌套关联不匹配的地方【英文标题】:Sequelize nested eager loading find all where nested association doesn't match 【发布时间】:2018-12-14 12:28:53 【问题描述】:

我正在尝试在我们的网站上设置自定义权限模块,并且对续集以及如何执行基本的嵌套急切加载操作相对较新。

我的设置方式是我有三个模型:PermissionPermissionDirectoryUser。权限在一个列表中,嵌套在它们与目录的belongsTo 关系中。我在列表中有一个过滤器,它根据用户是“允许”还是“拒绝”权限进行过滤。用户与权限之间存在多对多关系,我正在通过他们之间是否存在关联来确定他们是否“允许”权限。

有问题的页面是在过滤特定用户的权限时。过滤用户是否“允许”权限非常简单:

const directories = await models.PermissionDirectory.findAll(
  limit,
  offset,
  where:  ["$permissions.users.id$"], userId ,
  include: [
    
      model: models.Permission,
      include: [
        model: models.User
      ]
    ,
  ]
);

return directories;

但事实证明,按“拒绝”过滤很困难。执行相反的条件将返回其他用户拥有的权限,而不是返回目标用户(使用userId 参数指定)没有的权限。

where: ["$permissions.users.id$"], [Op.ne]: userId

这不起作用。举个例子,如果我正在查询以获取 User1 被“拒绝”的所有权限。如果 User1 有 Permission1 并且 User2 也有 Permission1,那么 Permission1 的目录将获得所有拥有非 User1 用户的权限。由于 User2 与 Permission1 和 User1.id != User2.id 相关联,因此 Permission1 将包含在响应中。

但是,我可以通过首先查询具有 userId 的所有权限,列出其 id 的列表,然后执行第二个查询来获取其 id 不在该列表中的权限,从而获得所需的效果。 . 但这需要两次调用而不是一次调用。

Tl;dr 我正在寻找一种方法来使用***权限目录进行嵌套急切加载查询,该目录将仅返回没有与给定用户关联的目录/权限。

【问题讨论】:

按照issue 中描述的一些方法,在尝试更直接地构建查询方面取得了一些进展。似乎 sequelize 在查询构建方面可能存在一些不足。 【参考方案1】:

经过大量的互联网搜索和许多死胡同,我想我知道这个问题的不幸答案:sequelize 不擅长构建复杂的查询。

为了使我的问题更加清晰,mysql join types 的轮廓将我的场景描述为Anti Semi Join。

为了在 sequelize 中实现这个 sql 查询,我需要能够执行一个子查询,该子查询似乎不被 sequelize 原生支持(根据问题 #3961 缺乏移动来衡量)。

在 where 语句中使用 sequelize.literal 似乎可以很好地满足我的需求,但是如果 sequelize 从一开始就将所有连接类型合并到它们的功能中,而不是仅支持内部连接和左连接,那就太好了.对我来说似乎是一种疏忽。

【讨论】:

你有没有想出一些额外的东西?我正在寻找在eager nested 列上使用where 条件的方法。

以上是关于Sequelize嵌套的渴望加载找到所有嵌套关联不匹配的地方的主要内容,如果未能解决你的问题,请参考以下文章

如何渴望加载多态关系的不同嵌套关系?

Laravel Eloquent:渴望加载多个嵌套关系

EF Core - 为啥“无限”嵌套急切加载?

如何在sequelize中对嵌套模型中的列进行排序?

sequelize 嵌套包含 where 子句

9. MyBatis加载策略