在 sequelize 和 apollo-server 中解析来自目标的源关联时理解 'include'
Understanding 'include' when resolving source association from target in sequelize and apollo-server
我正在为我的 apollo-server 编写一个解析器(使用 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
模型,因为 User
上不存在 profileId
外键)所以.. .我用的是include..
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??
}]
})
通过使用 include
选项,您正在 急切地加载 指定的关联模型。来自 docs:
When you are retrieving data from the database there is a fair chance that you also want to get associations with the same query - this is called eager loading.
当您 include
关联模型时,Sequelize 会在其生成的查询中附加一个连接语句。默认情况下,这是 LEFT OUTER JOIN
。这意味着如果你写:
User.findAll({ include: [{ model: Profile }] })
生成的查询将找到所有用户。如果用户碰巧有个人资料,则结果中的相关行也将包含个人资料字段。另一方面,我们可以通过添加 required
选项强制连接成为 INNER JOIN
:
User.findAll({ include: [{ model: Profile, required: true }] })
因为它是一个 INNER JOIN
,结果查询 returns 只有 个拥有个人资料的用户。
当您在 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 只需将 LIMIT
的 1 添加到查询中,该方法将解析为模型的单个实例而不是模型数组。
对连接的完整讨论超出了这个问题的范围。您可以查看这些其他问题以获取更多详细信息:
- What is the difference between “INNER JOIN” and “OUTER JOIN”?
- SQL join: where clause vs. on clause
我正在为我的 apollo-server 编写一个解析器(使用 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
模型,因为 User
上不存在 profileId
外键)所以.. .我用的是include..
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??
}]
})
通过使用 include
选项,您正在 急切地加载 指定的关联模型。来自 docs:
When you are retrieving data from the database there is a fair chance that you also want to get associations with the same query - this is called eager loading.
当您 include
关联模型时,Sequelize 会在其生成的查询中附加一个连接语句。默认情况下,这是 LEFT OUTER JOIN
。这意味着如果你写:
User.findAll({ include: [{ model: Profile }] })
生成的查询将找到所有用户。如果用户碰巧有个人资料,则结果中的相关行也将包含个人资料字段。另一方面,我们可以通过添加 required
选项强制连接成为 INNER JOIN
:
User.findAll({ include: [{ model: Profile, required: true }] })
因为它是一个 INNER JOIN
,结果查询 returns 只有 个拥有个人资料的用户。
当您在 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 只需将 LIMIT
的 1 添加到查询中,该方法将解析为模型的单个实例而不是模型数组。
对连接的完整讨论超出了这个问题的范围。您可以查看这些其他问题以获取更多详细信息:
- What is the difference between “INNER JOIN” and “OUTER JOIN”?
- SQL join: where clause vs. on clause