GraphQL 如何在子字段级别启用基于 ID 的查询?

Posted

技术标签:

【中文标题】GraphQL 如何在子字段级别启用基于 ID 的查询?【英文标题】:How can GraphQL enable an ID based query at sub fields level? 【发布时间】:2018-07-01 22:37:15 【问题描述】:

如果现有服务分别支持以下 GraphQL 查询:

查询某人的银行账户:

query 
    balance(id: "1") 
      checking
      saving
    

结果


  "data": 
    "balance": 
      "checking": "800",
      "saving": "3000"
    
  

查询某人的挂单:

query 
    pending_order(id: "1") 
      books
      tickets
    

结果


  "data": 
    "pending_order": 
      "books": "5",
      "tickets": "2"
    
  

实现上述功能的源代码是这样的:

module.exports = new GraphQLObjectType(
  name: 'Query',
  description: 'Queries individual fields by ID',

  fields: () => (
    balance: 
      type: BalanceType,
      description: 'Get balance',
      args: 
        id: 
          description: 'id of the person',
          type: GraphQLString
        
      ,
      resolve: (root,  id ) => getBalance(id)
    ,
    pending_order: 
      type: OrderType,
      description: 'Get the pending orders',
      args: 
        id: 
          description: 'id of the person',
          type: GraphQLString
        
      ,
      resolve: (root,  id ) => getPendingOrders(id)
    
  )
);

现在,我想让我的 GraphQL 服务架构支持人员级别的架构,即,

query 
    person (id: "1") 
      balance
      pending_order
    

并得到以下结果:


  "data": 
     "balance": 
       "checking": "800",
       "saving": "3000"
    
    "pending_order": 
      "books": "5",
      "tickets": "2"
    
  

如何重新构建架构,如何重用现有的查询服务?

编辑(阅读丹尼尔·里尔登的回答后)

我们能否优化 GraphQL 服务,以便我们根据查询进行服务调用?即,如果传入的查询是

query 
    person (id: "1") 
      pending_order
    

我的实际查询变成了

person: 
  ...
  resolve: (root,  id ) => Promise.all([
    getBalance(id)
  ]) => ( balance)

【问题讨论】:

【参考方案1】:

您将不得不定义一个单独的 Person 类型来包装 balancepending_order 字段。

module.exports = new GraphQLObjectType(
  name: 'Person',
  fields: () => (
    balance: 
      type: BalanceType,
      resolve: ( id ) => getBalance(id)
    ,
    pending_order: 
      type: OrderType,
      resolve: ( id ) => getPendingOrders(id)
    
  )
);

您需要在Query 类型中添加一个新字段:

person: 
  type: PersonType,
  args: 
    id: 
      type: GraphQLString
    
  ,
  // We just need to return an object with the id, the resolvers for
  // our Person type fields will do the result
  resolve: (root,  id ) => ( id )

要让事情更加干燥并重用现有代码,您无能为力。如果您正在寻找减少样板的方法,我建议您使用using graphql-tools。

【讨论】:

如果查询只需要一个字段,我们可以只调用一次吗? --见我上面的编辑

以上是关于GraphQL 如何在子字段级别启用基于 ID 的查询?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AppSync GraphQL 转换为双向一对多 @connection 执行字段级别 @auth?

GraphQL 字段是不是支持基于传入参数的多态性?

从 graphql 获取解析器级别的请求字段

Graphql - 如何获取选定字段的类型(字符串、整数、ID 等)

如何使用不同的字段生成相同的 graphql 查询

如何在 graphql 上正确创建 Id 字段以符合中继标准?