解决Graphql

时间:2017-03-21 23:19:24

标签: graphql apollo

GraphQL中有几个地方需要解析Type而不只是field中的Type

后端API -

  • /users - 用户列表 - 最小信息 - 名称,ID
  • /users/:id - 详细的用户信息
  • /foo - 返回字段所有者,即UserID

查询和架构

构建架构以执行以下查询

query a {
  users {
    age # some detail info
  }
  foo {
    owner {
      location # some detail info
    }
  }
}

,架构可以如下 -

type Query {
  users: [User]
  foo: Foo
}
type Foo {
  owner: User
}
type User {
  id: ID
  age: Int
  location: String
}

问题

上述模式中的解析器需要包含/处理在两个不同位置的用户详细信息获取调用。 1.用户列表 - Query.users和2. Query.foo.owner。并且必须记住处理此类型,您只有一个用户ID才能将其转换为实际用户。

可能的解决方案

在撰写本文时,GraphQL支持resolveTypeInterface上的Union。无法为整个Type指定解析程序 - 只有field中的Type才能拥有解析程序。因此,如果可以在GraphQL中解析类型,这将使​​其更容易实现。

替代解决方案

由于只能解析Type中的字段,因此可以创建一个额外的type并在解析器中的Type中维护此字段的处理,并且位于一个位置。但现在,查询比以前更深了1级。

query b {
  users {
    details {
      age
    }
  }
  foo {
    owner {
      details {
        location
      }
    }
  }
}

其他类似场景

由于无法在GraphQL中解析Type,因此enums面临同样的问题。当您在API响应中有一个特殊字符并且该字段是ENUM时,您要么记得在使用此枚举的所有位置处理它,要么创建一个额外的类型来表示此枚举。

我使用ApolloGraphQL为所有这些案例创建了一个最小的repro - https://github.com/boopathi/graphql-test-1

问题

  1. 架构/语言是否支持指定如何处理特定类型/为Type指定解析器而不仅仅是Type中的字段?如果没有,为什么?
  2. 如何在架构中处理这些事情。还有其他方法可以做这些事吗?

1 个答案:

答案 0 :(得分:2)

你是对的 - 这在GraphQL中肯定是有点奇怪的。从本质上讲,由于解析器的工作方式,它是来自的类型,而不是转到的类型,它负责获取正确的数据。< / p>

这种方法有利有弊。您可以想象一下GraphQL的实现,其中父对象只返回一个ID,然后您就知道如何获取详细信息的每种类型都有一个解析器。我认为在某些情况下肯定会更好。

以下是我们目前建议如何构建代码以避免这种耦合:

  1. 为您拥有的不同后端数据源和对象类型定义模型类或存储库对象
  2. 在解析器中使用它们而不是直接访问数据库
  3. 为了实现穷人的依赖注入,我们将它们放在服务器的context上。当你把它们放在一起时,它看起来像这样:

    架构:

    # Information about a GitHub repository submitted to GitHunt
    type Entry {
      # Information about the repository from GitHub
      repository: Repository!
      # The GitHub user who submitted this entry
      postedBy: User!
      ...
    

    解析器:

    export const resolvers = {
      Entry: {
        repository({ repository_name }, _, context) {
          return context.Repositories.getByFullName(repository_name);
        },
        postedBy({ posted_by }, _, context) {
          return context.Users.getByLogin(posted_by);
        },
        ...
    

    您可以在GitHunt-API示例应用中的整个服务器的上下文中看到这一点。

    基本上,这种方法使用解析器作为一个瘦包装器来调用底层业务逻辑,就像路由器一样。这与有关服务器at Facebookotherwise的当前文献一致。