在 sequelize 和 apollo-server 中从目标解析源关联时理解“包含”

Posted

技术标签:

【中文标题】在 sequelize 和 apollo-server 中从目标解析源关联时理解“包含”【英文标题】:Understanding 'include' when resolving source association from target in sequelize and apollo-server 【发布时间】:2019-05-23 04:00:18 【问题描述】:

我正在为我的 apollo 服务器编写一个解析器(使用 sequelize),并且正在努力理解这种向后关联的解析是如何工作的……我对我的 sequelize 查询中的 include 是如何工作的感到非常困惑。

我的模特协会:

User.hasOne(models.Profile)  <- so the foreign key 'userId' is on the profile table

Profile.belongsTo(models.User) <- foreign key 'userId' still on profile table

我的 graphql 架构:

type Profile 
  id: ID!
  user: User!

我的解析器:(我无法使用where: profileId: profile.id 查询User 模型,因为profileId 外键在User 上不存在)所以...我使用包含...

Profile: 
  user: async (profile, _args,  models ) => 
    return await models.User.findOne(
      include: [
        model: models.Profile,
        where:  id: profile.id  <- this makes zero sense to me.. id is the id of the Profile row? how does this work??
      ]
    )

【问题讨论】:

【参考方案1】:

通过使用include 选项,您急切地加载指定的关联模型。来自docs:

当您从数据库中检索数据时,您很有可能还希望获得与同一查询的关联 - 这称为预加载。

当您include 关联模型时,Sequelize 会在其生成的查询中附加一个连接语句。默认情况下,这是一个LEFT OUTER JOIN。这意味着如果你写:

User.findAll( include: [ model: Profile ] )

生成的查询将找到所有用户。如果用户碰巧有个人资料,结果中的相关行也将包括个人资料字段。另一方面,我们可以通过添加required 选项来强制连接为INNER JOIN

User.findAll( include: [ model: Profile, required: true ] )

因为它是INNER JOIN,所以生成的查询返回拥有个人资料的用户。

当您在include 中添加where 时,JOIN 会自动转换为INNER JOIN(除非您将required 显式设置为false)。 where 子句本身实际上成为INNER JOINON 语句的一部分。所以如果我们写:

User.findAll( include: [ model: Profile, where:  id: 'someId'  ] )

结果将包括所有拥有个人资料的用户,其中个人资料的 id 等于 someIdwhere 始终特定于我们所包含的模型,因此无需指定我们感兴趣的模型的 id 字段。

最后,如果使用 findOne 而不是 findAll,Sequelize 只需将 1 的 LIMIT 添加到查询中,并且该方法解析为模型的单个实例而不是数组。

关于联接的完整讨论超出了此问题的范围。您可以查看这些其他问题以了解更多详情:

What is the difference between “INNER JOIN” and “OUTER JOIN”? SQL join: where clause vs. on clause

【讨论】:

以上是关于在 sequelize 和 apollo-server 中从目标解析源关联时理解“包含”的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Express 和 Apollo-Server 获取 HTTP 授权标头

Apollo-server 2 验证中间件

在客户端处理 apollo-server 错误

登录 apollo-server 的推荐方式

如何在本地网络上部署带有 apollo 客户端和 apollo-server 后端的 React 应用程序

使用纱线工作区时,tsc 在 apollo-server 中找不到 express 的声明文件