在 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 JOIN
的ON
语句的一部分。所以如果我们写:
User.findAll( include: [ model: Profile, where: id: 'someId' ] )
结果将包括所有拥有个人资料的用户和,其中个人资料的 id 等于 someId
。 where
始终特定于我们所包含的模型,因此无需指定我们感兴趣的模型的 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 授权标头