首页 > 解决方案 > 在 sequelize 和 apollo-server 中从目标解析源关联时理解“包含”

问题描述

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

我的模特协会:

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}profileIdUser

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??
      }]
    })

标签: sequelize.jsgraphqlapollo-server

解决方案


通过使用该include选项,您可以急切地加载指定的关联模型。从文档

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

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

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

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

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

因为它是INNER JOIN,所以生成的查询返回具有配置文件的用户。

当您在where中添加 a 时include,JOIN 会自动转换为 an INNER JOIN(除非您明确设置requiredfalse)。ONwhere子句本身实际上成为INNER JOIN. 所以如果我们写:

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

结果将包括所有拥有个人资料并且该个人资料的 id 等于 的用户someId。总是特定于我们所包含的where模型,因此无需指定id我们感兴趣的模型字段。

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

对连接的完整讨论超出了这个问题的范围。您可以查看这些其他问题以获取更多详细信息:


推荐阅读