[英]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_id
和salary_grade
列,即使它们将作为模式中不同类型的字段公开。__typename
(稍后会详细介绍)会很有帮助。__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.