如何为 GraphQL Mutation 字段编写解析器

Posted

技术标签:

【中文标题】如何为 GraphQL Mutation 字段编写解析器【英文标题】:How to write resolvers for GraphQL Mutation fields 【发布时间】:2019-04-03 14:38:33 【问题描述】:

我的 GraphQL 架构如下所示:

type Outer 
   id: ID
   name: String,
   inner: [Inner]


type Inner 
   id: ID
   name: String


input OuterInput 
   name: String,
   inner: InnerInput


Input InnerInput 
   name: String


type Query 
   getOuter(id: ID): Outer


type Mutation 
   createOuter(outer: OuterInput): Outer

在数据库中,外部对象是这样存储的:


   id: 1,
   name: ‘test’,
   inner: [5, 6] //IDs of inner objects. Not the entire inner object

外部和内部存储在单独的数据库集合/表中(我使用的是 DynamoDB)

我的解析器如下所示:

Query: 
   getOuter: (id) => 
      //return ‘Outer’ object with the ‘inner’ IDs from the database since its stored that way
   



Outer: 
   inner: (outer) => 
      //return ‘Inner’ objects with ids from ‘outer.inner’ is returned
   


Mutation: 
   createOuter: (outer) => 
      //extract out the IDs out of the ‘inner’ field in ‘outer’ and store in DB.
   


OuterInput: 
   inner: (outer) => 
      //Take the full ‘Inner’ objects from ‘outer’ and store in DB.
     // This is the cause of the error
   

但我无法为“OuterInput”中的“inner”字段编写解析器,类似于我为“Outer”所做的。 GraphQL 抛出错误说

Error: OuterInput was defined in resolvers, but it's not an object

如果不允许为输入类型编写解析器,我该如何处理?

【问题讨论】:

【参考方案1】:

输入类型不需要解析器。输入类型仅作为值传递给字段参数,这意味着它们的值是已知的——它不需要由服务器解析,这与查询中返回的字段值不同。

每个解析器的签名都是相同的,包括 4 个参数:1) 父对象,2) 正在解析的字段的参数,3) 上下文和 4) 包含有关请求的更详细信息的对象作为整个。

因此,要访问 outer 参数的 createOuter 突变:

Mutation: 
   createOuter: (root, args, ctx, info) => 
      console.log('Outer: ', args.outer)
      console.log('Outer name: ', args.outer.name)
      console.log('Inner: ', args.outer.inner)
      console.log('Inner name: ', args.outer.inner.name)
      // resolver logic here
   

【讨论】:

嘿,我很抱歉没有提供更多信息来说明我在我的问题中想要达到的目标。在查询部分中,“外部”和“内部”的获取位于单独的解析器中。 getOuter 将只从数据库中获取“Outer”对象,如果查询类似于 getOuter(id: 1) name inner ,那么要获取“Inner”对象,graphql 将调用 Outer.inner 解析器。我也在 Mutations 中寻找类似的分离。如果给出了没有 'inner' 的 'Outer' 对象,则调用 createOuter。如果 'Outer' 中的 'inner' 存在,则会再调用一个解析器。 如果我正确理解了您的问题,则没有传统的方法可以做到这一点。同样,解析器用于解析字段的值,而不是输入。 GraphQL 只对输入进行类型检查——它不会像对字段值那样遍历所有节点,因为这些值是已知的并且没有什么要解决的。如果您有某种逻辑“如果给出 foo,则执行此操作;如果给出 bar,则执行此操作”,则该逻辑将需要包含在您的突变解析器中。 充其量,您可以提取出某种辅助函数,该函数将遍历给定的参数,并根据参数对象的结构找出需要采取的操作。然后可以在您的解析器中重用该函数。 是的,这听起来是个好主意。将创建一个单独的帮助层来委派嵌套输入类型的执行。

以上是关于如何为 GraphQL Mutation 字段编写解析器的主要内容,如果未能解决你的问题,请参考以下文章

如何为graphql类型的字段对象添加排序,引用不同的graphql类型?

如何为 xunit 集成测试编写 GraphQL 变异查询

如何为 TypeScript 配置 `*.graphql` 导入?

Angular Apollo:错误:GraphQL 错误:“Mutation”类型的字段“AuthLogin”上的未知参数“用户名”

GraphQL Mutation 更新数据库中的字段数组

Apollo GraphQL“不能为不可为空的字段 Mutation.createUser 返回 null”