繁体   English   中英

GraphQL 联合和续集

[英]GraphQL Unions and Sequelize

我无法理解如何从 GraphQL 联合检索信息。 我有这样的东西:

const Profile = StudentProfile | TeacherProfile

然后在我的解析器中,我有:

  Profile: {
    __resolveType(obj, context, info) {
      if (obj.studentId) {
        return 'StudentProfile'
      } else if (obj.salaryGrade) {
        return 'TeacherProfile'
      }
    },
  },

这不会引发任何错误,但是当我运行这样的查询时:

query {
  listUsers {
    id
    firstName
    lastName
    email
    password
    profile {
      __typename
      ... on StudentProfile {
        studentId
      }
      ... on TeacherProfile {
         salaryGrade
     }
    }
  }
}

这将返回除仅返回null profile 之外的所有内容。 我使用 Sequelize 来处理我的数据库工作,但我对 Unions 的理解是它会简单地查找被查询 ID 的相关类型并在查询中返回适当的详细信息。

如果我弄错了,我怎样才能让这个查询工作?

编辑:

我的列表用户解析器:

const listUsers = async (root, { filter }, { models }) => {
  const Op = Sequelize.Op
  return models.User.findAll(
    filter
      ? {
          where: {
            [Op.or]: [
              {
                email: filter,
              },
              {
                firstName: filter,
              },
              {
                lastName: filter,
              },
            ],
          },
        }
      : {},
  )
}

用户模型关系(非常简单,与个人资料无关):

User.associate = function(models) {
    User.belongsTo(models.UserType)
    User.belongsTo(models.UserRole)
  }

和我的通用用户解析器:

User: {
    async type(type) {
      return type.getUserType()
    },

    async role(role) {
      return role.getUserRole()
    },
  },

解决此问题的最简单方法是使用单个表(即单个表继承)。

  • 创建一个包含所有类型列的表。 例如,它会同时包含student_idsalary_grade列,即使它们将作为模式中不同类型的字段公开。
  • 添加标识每一行的实际类型的“类型”列。 在实践中,将此列__typename (稍后会详细介绍)会很有帮助。
  • 为您的表创建一个 Sequelize 模型。 同样,此模型将包括所有属性,即使它们不适用于特定类型。
  • 定义你的 GraphQL 类型和你的接口/联合类型。 您可以提供一个__resolveType方法,该方法根据您添加的“类型”字段返回适当的类型名称。 但是,如果您将此字段命名为__typename并使用您公开的 GraphQL 类型的名称填充它,您实际上可以跳过这一步!
  • 您可以像平常一样使用您的模型,利用find方法来查询您的表或创建与它的关联。 例如,您可以添加像User.belongsTo(Profile)这样的关系,然后延迟加载它: User.findAll({ include: [Profile] })

这种方法的最大缺点是您会丢失数据库和模型级别的验证。 也许对于一个TeacherProfile salary_grade永远不应该是 null ,但是你不能用约束来强制执行这个,或者将属性的allowNull属性设置为false 充其量只能依靠 GraphQL 的类型系统来强制验证,但这并不理想。

可以更进一步,为每个单独的“类型”创建额外的 Sequelize 模型。 这些模型仍会指向同一个表,但只会包含特定于您为每种类型公开的字段的属性。 这样,您至少可以在模型级别强制执行“必需”属性。 然后,例如,您使用Profile模型查询所有配置文件,但在插入或更新教师配置文件时使用TeacherProfile 这很有效,但请注意,在构建这样的模型时不能使用sync方法——您需要手动处理迁移。 无论如何你都不应该在生产中使用sync ,所以这不是什么问题,但绝对需要注意。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM