在 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 JOINON 语句的一部分。所以如果我们写:

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

结果将包括拥有配置文件 的所有用户,其中该配置文件的 ID 等于 someIdwhere 始终特定于我们包含的模型,因此无需指定我们感兴趣的模型的 id 字段。

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

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

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