GraphQLInterfaceType和GraphQLUnionType的真实示例
我很难理解何时使用GraphQLInterfaceType和GraphQLUnionType的真实示例,graphql,graphql-js,Graphql,Graphql Js,我很难理解何时使用GraphQLInterfaceType和GraphQLUnionType 我有RTFMs: 有谁能提供一个真实世界的例子来帮助我理解这个问题吗?GraphQLInterfaceType的语义与大多数程序语言的接口类似。graphql为它添加了更多的行为。类似于检查派生类是否实现了所有字段,动态解析到派生实例。 GraphQLUnionType的语义不是一个Union,而是类似于或(有点像flowtype的类型检查? 一个真实的例子是=>中继的节点设计。 GraphQL
GraphQLInterfaceType
和GraphQLUnionType
我有RTFMs:
有谁能提供一个真实世界的例子来帮助我理解这个问题吗?GraphQLInterfaceType的语义与大多数程序语言的
接口类似。graphql为它添加了更多的行为。类似于检查派生类是否实现了所有字段,动态解析到派生实例。
GraphQLUnionType
的语义不是一个Union
,而是类似于或(有点像flowtype的类型检查?
一个真实的例子是=>中继的节点设计。
GraphQLInterfaceType
与GraphQLUnionType
完全无关
我想你可能被这搞糊涂了?
interface Node{
id: string
}
type Dog implements Node{
id: string
}
type Cat implements Node{
id: string
}
union Animal = Dog | Cat
type User{
node: Node
animal: Animal
}
如果你对此感到困惑,你应该读一些强类型语言的书。(比如C#或Java或其他东西。也许你也应该看看流,这种用法Dog | Cat
是一种类型限制)都是为了帮助你设计一个具有异构类型集的模式,您可以使用这两种方法实现相同的功能,但是当类型基本相同但某些字段不同时,GraphQLUnionType
更适合,而当类型完全不同且具有完全不同的字段时,GraphQLUnionType
更适合
最终,是否使用其中一种取决于您的模式设计
对于一个真实的例子,假设您有一个博客列表,但是使用框架a的博客使用用户名和密码作为身份验证,使用框架B的博客使用电子邮件和密码。我们使用图形接口类型设计它,如下所示:
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;
}
query MyQuery {
blogs: {
url
password
... on BlogA {
email
}
... on BlogB {
username
}
}
}
query MyQuery {
blogs: {
url
auth {
... on AuthA {
username
password
}
... on AuthB {
email
password
}
}
}
}
当我们创建一个新的博客发送username
,它将创建一个BlogA
我们可以这样查询:
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;
}
query MyQuery {
blogs: {
url
password
... on BlogA {
email
}
... on BlogB {
username
}
}
}
query MyQuery {
blogs: {
url
auth {
... on AuthA {
username
password
}
... on AuthB {
email
password
}
}
}
}
现在让我们使用graphqluontype
获得相同的功能,因为我们更喜欢使用一种类型的博客和两种类型的身份验证方法:
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;
}
我们可以这样查询:
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;
}
query MyQuery {
blogs: {
url
password
... on BlogA {
email
}
... on BlogB {
username
}
}
}
query MyQuery {
blogs: {
url
auth {
... on AuthA {
username
password
}
... on AuthB {
email
password
}
}
}
}
正如您在本例中所看到的,我们通过接口或联合实现了相同的功能,但是根据您的模式设计,其中一个可能更合适
例如,假设您想添加一个同样使用电子邮件和密码的博客框架C。您需要包含另一个字段,以便能够在我们的resolveBlogType
函数中将其与blog框架B区分开来。让我们添加type
字段。在我们的联合示例中,由于我们只能访问联合中的字段,因此您需要向联合添加type
。如果将来我们想为多个框架添加另一个具有相同字段的Union,那么我们还需要在那里添加type
字段。在我们的模式中重复多次type
不是件好事。最好使用一个接口,让所有使用接口的对象在resolveBlogType
函数中都可以访问一个type
字段。当您在中继片段上查询blogs
时,这与graphql相对应的是什么?我看到您的graphql接口类型名为Blog
,您需要创建blogs
查询,该查询不在示例代码中。我仍然不确定我是否理解,当使用这个示例时,我得到了错误:…\node\u modules\graphql\type\schema.js:295
throw\u iteratorerror
^
类型错误:graphQLType.getFields不是一个函数
@AlexanderPravdin它实际上没有显示在文档中,但字段需要是一个返回对象的函数,您可以参考这个非常有用的视频的js部分: