两者都旨在帮助您设计具有一组异构类型的模式,并且您可以使用两者来实现相同的功能,但是GraphQLInterfaceType
当类型基本相同但某些字段不同时更合适,并且GraphQLUnionType
类型是完全不同,有完全不同的领域。
最终是否使用其中一个取决于您的架构设计。
对于一个真实的例子,假设你有一个博客列表,但是使用框架 A 的博客使用用户名和密码作为身份验证,使用框架 B 的博客使用电子邮件和密码。我们用GraphQLInterfaceType
这样的方式设计它:
const BlogType = new GraphQLInterfaceType({
name: 'Blog',
fields: {
url: { type: new GraphQLNonNull(GraphQLString) }
password: { type: new GraphQLNonNull(GraphQLString) }
},
resolveType: resolveBlogType
});
const BlogAType = new GraphQLObjectType({
name: 'BlogA',
interfaces: [Blog],
fields: {
url: { type: new GraphQLNonNull(GraphQLString) }
username: { type: new GraphQLNonNull(GraphQLString) },
password: { type: new GraphQLNonNull(GraphQLString) }
}
});
const BlogBType = new GraphQLObjectType({
name: 'BlogB',
interfaces: [Blog],
fields: {
url: { type: new GraphQLNonNull(GraphQLString) }
email: { type: new GraphQLNonNull(GraphQLString) },
password: { type: new GraphQLNonNull(GraphQLString) }
}
});
function resolveBlogType(value) {
return value.username ? BlogAType : BlogBType;
}
当我们创建一个新的博客发送username
时,它会创建一个BlogA
.
我们可以这样查询:
query MyQuery {
blogs: {
url
password
... on BlogA {
email
}
... on BlogB {
username
}
}
}
现在让我们使用 获得相同的功能GraphQLUnionType
,因为我们更喜欢只使用一种类型的博客和两种类型的身份验证方法:
const AuthAType = new GraphQLObjectType({
name: 'AuthA',
fields: {
username: { type: new GraphQLNonNull(GraphQLString) },
password: { type: new GraphQLNonNull(GraphQLString) }
}
});
const AuthBType = new GraphQLObjectType({
name: 'AuthB',
fields: {
email: { type: new GraphQLNonNull(GraphQLString) },
password: { type: new GraphQLNonNull(GraphQLString) }
}
});
const AuthType = new GraphQLUnionType({
name: 'Auth',
types: [AuthAType, AuthBType]
resolveType: resolveAuthType
});
const BlogType = new GraphQLInterfaceType({
name: 'Blog',
fields: {
url: { type: new GraphQLNonNull(GraphQLString) }
auth: { type: AuthType }
},
});
function resolveAuthType(value) {
return value.username ? AuthAType : AuthBType;
}
我们可以这样查询:
query MyQuery {
blogs: {
url
auth {
... on AuthA {
username
password
}
... on AuthB {
email
password
}
}
}
}
正如您在此示例中所看到的,我们使用接口或联合实现了相同的功能,但根据您的模式设计,其中一个可能更合适。
例如,假设您要添加一个博客框架 C,它也使用电子邮件和密码。您需要包含另一个字段,以便能够在我们的resolveBlogType
函数中将其与博客框架 B 区分开来。让我们添加type
字段。在我们的联合示例中,由于我们只能访问联合中的字段,因此您需要添加type
到联合中。如果将来我们想为多个框架添加另一个具有相同字段的联合,我们也需要在type
那里添加该字段。type
在我们的模式中重复多次并不太好。使用接口可能是一个更好的主意,并且使用该接口的所有对象都可以在函数中访问单个type
字段。resolveBlogType