在GraphQL中解决类型问题

9

在GraphQL中有一些地方需要解析Type而不仅是Type中的field

后端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支持InterfaceUnion上的resolveType。无法为整个Type指定解析器-只有Type中的field可以具有解析器。因此,如果可以在GraphQL中解析类型,则会使其更简单实现。

备选解决方案

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

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

其他类似的场景

由于GraphQL中无法解析Type,因此enums面临相同的问题。当API响应中存在特殊字符并且该字段为ENUM时,您可以在使用此enum的所有位置上记得处理它,或者创建一个额外的类型来表示此enum。

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

问题

  1. 架构/语言是否支持指定如何处理特定类型/指定Type的解析器,而不仅仅是Type中的字段?如果不支持,为什么?
  2. 您如何在架构中处理这些内容?还有其他方法吗?
1个回答

4
你说得对 - 这在GraphQL中确实有些奇怪。基本上,由于解析器的工作方式,负责获取正确数据的是你从中来的类型,而不是你要去的类型。
这种方法有利有弊。你可以想象一种实现GraphQL的方法,其中父对象只返回一个ID,然后每个类型都有一个解析器,知道如何获取详细信息。我认为这对某些情况肯定更好。
以下是我们目前建议的代码结构,以避免这种耦合:
  1. 为您拥有的不同后端数据源和对象类型定义模型类或存储库对象
  2. 在解析器中使用它们,而不是直接访问数据库
为了实现贫民版依赖注入,我们将这些放在服务器的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示例应用中查看整个服务器的上下文。
基本上,这种方法使用解析器作为调用底层业务逻辑的薄包装器,几乎像路由器一样。这与当前关于Facebook其他地方的服务器文献一致。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接