GraphQL 解析器问题

Posted

技术标签:

【中文标题】GraphQL 解析器问题【英文标题】:GraphQL Resolver Problems 【发布时间】:2020-01-18 08:49:47 【问题描述】:

我花了很多时间阅读 GraphQL 教程,但不幸的是,它们似乎没有涵盖足够深入的内容,让我无法理解。对于这个真实世界的例子,我真的很感激。

在示例中,查询放置在解析器对象的根目录;我可以让它对单级查询正常工作。当我尝试解析嵌套查询时,嵌套解析器永远不会被调用。令我非常困惑的是,我发现的每个教程都不是在 graphql 网站上发布的,都放在一个 Query 对象中,并将它们的查询嵌套在它之下,而不是根级别。

考虑以下架构:

type Product 
  id: String!
  retailerId: String!
  title: String!
  description: String
  price: String!
  currency: String!


type OrderLine 
  product: Product!
  quantity: Int!


type Order 
  id: String!
  retailerId: String!
  orderDate: Date!
  orderLines: [OrderLine!]!


type Query 
  product(id: String!): Product
  order(id: String!): Order


schema 
    query: Query

还有以下查询:

query 
    order(id: "1") 
        id
        orderLines 
            quantity
        
    

我已经尝试了多个版本的解析器(现在只是测试数据),但似乎没有一个能返回我所期望的。这是我当前的解析器实现:

const resolvers = 
  OrderLine: 
    quantity: () => 1,
  ,
  Order: 
    orderLines: (parent: any, args: any) =>  console.log("Calling order lines"); return []; ,
  ,
  Query: 
    product(parent, args, ctx, other) 
      return  id: args.id.toString(), test: true ;
    ,
    order: ( id ) =>  console.log("Calling order 1"); return  id: id.toString(), testOrder: true, orderLines: [] ; ,
  ,
  order: ( id ) =>  console.log("Calling order 2"); return  id: id.toString(), testOrder: true, orderLines: [] ; ,
;

在控制台中我可以观察到“调用订单 2”日志消息,“调用订单行”没有日志,订单行数组为空。

所以两部分的问题:

1) 为什么在上面的例子中它点击“Calling order 2”而不是“Calling order 1”?

2) 为什么上述方法不适用于嵌套查询 Order.OrderLines?

提前致谢!

【问题讨论】:

不确定是否值得注意,但该架构是使用 npm 库“graphql”中的 buildSchema 构建的。 【参考方案1】:

查询中

type Query 
  product(id: String!): Product
  order(id: String!): Order
  users: User

schema 
    query: Query

在解析器中

const resolvers = 
  order: ( id ) => function
  product: ( id ) => function

Graphql 致力于查询解析器的概念。如果您想要任何查询(示例用户),您必须有 解析器(即用户)返回具有用户类型定义的用户。 Graphql 查询是交互式且区分大小写的 下一步是实现订单/产品查询的解析器功能。 事实上,我们还没有提到的一件事是,不仅根字段, 但实际上 GraphQL 模式中类型的所有字段都有解析器函数。

1) 为什么在上面的例子中它点击“Calling order 2”而不是“Calling order 1”? 在这个查询中

 query 
    order(id: "1") 
        id
        orderLines 
            quantity
        
    
  

然后它去订单返回带有定义类型的订单

2) 为什么上述方法不适用于嵌套查询 Order.OrderLines?

You can only use two query first order and second product only as per your schema

请查看文档以了解此要求的嵌套查询。

【讨论】:

【参考方案2】:

如果您使用buildSchema 生成架构,则为字段提供解析器的唯一方法是通过根对象。但这更像是一种技巧——您实际上并没有覆盖字段的默认解析器,因此,您基本上仅限于使用根级字段(因为您正在努力学习)。这就是为什么只调用Query.order 函数的原因——这是一个根级字段。详细解释了为什么通过根(种类)传递函数的工作原理here。

底线是你shouldn't be using buildSchema。如果您想使用 SDL 来定义您的架构,请迁移到使用 Apollo Server。

【讨论】:

它也不适用于 Apollo 服务器,并且表示不支持:github.com/apollographql/graphql-tools/issues/1026 @DeveloperDave 我不确定你指的是什么。在使用 Apollo Server 时,支持为任何字段提供解析器,而不仅仅是根字段,这是 OP 遇到的问题。您链接的问题仅指用于定义解析器映射的一些不受支持的语法。 不。您误解了他的问题(谷歌似乎理解它,因为除了 Github 问题线程之外,它还提到了这个 *** 问题线程)。两者都提到了在排除为什么不调用 nested 解析器时出现的挑战。昨晚我也遇到了同样的问题,我的一个查询的响应对象的“孙子”字段上的解析器没有被调用。此外,无论您是否使用 Apollo / graphql-tools 都会出现此问题(我正在使用它,该 github 问题线程上的绅士也是如此)。

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

GraphQL 解析器应该有多懒?

graphql-yoga - GraphQL 解析器参数在哪里定义和记录?

Apollo GraphQL - 未触发解析器

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

graphql 解析器优化

如何模拟 mongodb 以进行单元测试 graphql 解析器