【问题标题】:Real world example of GraphQLInterfaceType and GraphQLUnionTypeGraphQLInterfaceType 和 GraphQLUnionType 的真实示例
【发布时间】:2016-04-16 01:33:24
【问题描述】:

我很难理解何时使用GraphQLInterfaceTypeGraphQLUnionType

我有 RTFM:

谁能提供一个真实世界的例子,当这些对我的笨蛋有用时?

【问题讨论】:

    标签: graphql graphql-js


    【解决方案1】:

    GraphQLInterfaceType 的语义类似于大多数程序语言的 interface 。并且 graphql 为它添加了更多的行为。比如检查派生类是否实现了所有字段,动态解析派生实例。
    GraphQLUnionType 的语义不是 Union ,而是类似于 OR 的东西。(有点像 flowtype 的类型检查?)
    一个真实的例子是example in Relay => Relay 的节点设计。
    GraphQLInterfaceTypeGraphQLUnionType 完全无关。
    我想你可能对此感到困惑?

    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 或其他。也许您也应该看看 Flow,这种用法 Dog|Cat 是类型限制)

    【讨论】:

      【解决方案2】:

      两者都旨在帮助您设计具有一组异构类型的架构,并且您可以使用两者实现相同的功能,但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 在我们的模式中重复多次并不太好。使用接口可能是一个更好的主意,并且使用该接口的所有对象都可以在 resolveBlogType 函数中访问单个 type 字段。

      【讨论】:

      • 当您在中继片段上查询 blogs 时,这与 graphql-wise 对应的是什么?我看到你的 graphql 接口类型被命名为 Blog
      • 您需要创建blogs 查询,该查询不在示例代码中
      • 我还是不明白
      • 按原样使用此示例时出现错误:...\node_modules\graphql\type\schema.js:295throw _iteratorError2;^TypeError: graphQLType.getFields is not a function
      • @AlexanderPravdin 它实际上并没有在文档中显示,但是字段需要是一个返回对象的函数,您可以参考这个非常有用的视频的 js 部分:youtube.com/watch?v=UBGzsb2UkeY
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-15
      相关资源
      最近更新 更多