在序列化和阿波罗服务器中从目标解析源关联时理解“包含”

时间:2018-12-23 17:44:27

标签: sequelize.js graphql 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!
}

我的解析器:(我无法使用User来查询where: {profileId: profile.id}模型,因为profileId上没有User外键)所以...我使用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??
      }]
    })

1 个答案:

答案 0 :(得分:1)

使用include选项,您热切加载指定的关联模型。来自docs

  

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

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

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

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

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

由于它是INNER JOIN,因此结果查询仅返回具有配置文件的用户

where内添加include时,JOIN会自动转换为INNER JOIN(除非您将required显式设置为false)。 where子句实际上实际上成为ON的{​​{1}}语句的一部分。因此,如果我们写:

INNER JOIN

结果将包括具有配置文件的所有用户,该配置文件的ID等于User.findAll({ include: [{ model: Profile, where: { id: 'someId' } }] }) someId始终特定于我们要包括的模型,因此无需指定我们感兴趣的模型的where字段。

最后,如果使用id而不是findOne,则Sequelize会简单地向查询添加findAll的1,并且该方法将解析为Model的单个实例而不是数组。

关于联接的完整讨论不在此问题的范围内。您可以查看其他问题以获取更多详细信息: