在 Graphql 中解析类型

Posted

技术标签:

【中文标题】在 Graphql 中解析类型【英文标题】:Resolving Types in Graphql 【发布时间】:2017-08-13 21:07:03 【问题描述】:

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

后端 API -

/users - 用户列表 - 最少信息 - 姓名、ID /users/:id - 详细的用户信息 /foo - 返回一个字段所有者,它是一个用户 ID

查询和架构

构建架构以执行以下查询

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

问题

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

可能的解决方案

在撰写本文时,GraphQL 在InterfaceUnion 上支持resolveType。无法为整个 Type 指定解析器 - 只有 Type 中的 field 可以有解析器。因此,如果可以在 GraphQL 中解析一个类型,这将使​​其更易于实现。

替代解决方案

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

query b 
  users 
    details 
      age
    
  
  foo 
    owner 
      details 
        location
      
    
  

其他类似场景

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

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

问题

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

【问题讨论】:

【参考方案1】:

你是对的 - 这绝对是 GraphQL 中有点奇怪的东西。本质上,由于解析器的工作方式,负责获取正确数据的是您来自的类型,而不是您要去的类型。

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

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

    为您拥有的不同后端数据源和对象类型定义模型类或存储库对象 使用解析器中的那些而不是直接访问数据库

为了实现一个穷人的依赖注入,我们将它们放在服务器的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 Facebook 和otherwise 的文献一致。

【讨论】:

以上是关于在 Graphql 中解析类型的主要内容,如果未能解决你的问题,请参考以下文章

NodeJs 中的 GraphQl - 对象类型的解析器

如何解析 GraphQL 中的嵌套类型?

用于解析器 GraphQL 瑜伽的 TypeScript 类型(在上下文中使用 prisma2)

如何使用 graphql-tools 使用或解析枚举类型?

类型 Graphql 自定义解析器

在 NestJS + GraphQL 中实现“命名空间类型”解析器