【问题标题】:GraphQL filtering parent data in child resolverGraphQL 在子解析器中过滤父数据
【发布时间】:2019-07-14 12:21:48
【问题描述】:

我试图弄清楚如何使用 GraphQL 在父子关系中实现自下而上的过滤。

考虑以下对停车场和可用停车位进行建模的基本类型层次结构:

type ParkingLot {
  id: Int!
  spots: [ParkingSpot]
}

type ParkingSpot {
  id: Int!,
  occupied: Boolean!
}

我想以一种能够检索所有至少有一个空闲停车位的停车场的方式实施我的解析器。

query AllParkingLotsWithStatus($status : Boolean = false) {
   ParkingLot {
     id 
     spots(occupied: $status)  {
       id
     }
   }
}

我正在使用的 GraphQL 的具体实现是基于 PHP 的,并且可用 here,但任何基于 JS 的实现都会非常有助于为我指明正确的方向。我知道那里有支持使用“where:”参数进行过滤的库,但我必须自己实现这个机制,因为我使用的库不提供开箱即用的功能。

我探索的一个想法是在 ParkingLot 的解析器中简单地编写一个 JOIN 语句,但我觉得这不符合 GraphQL 的精神。

我想到的另一个想法是重写查询,使其首先检索 ParkingSlots,并且仅在其状态可用时才获取其父级。但是,这可能是计算密集型的,因为停车场比停车位少,因此从父级到子级导航关系的计算密集度可能会更低。

您会建议哪种方法不归结为更改类型层次结构(我无法做到这一点)。是否有一种方法可以在子节点的解析器中发生某些情况时立即拒绝父节点,或者这是否会被认为超出 GraphQL 实现的范围,更像是正在使用的实际库的功能?我想因为那里的一些库支持使用“where:”子句进行过滤,所以这必须是可能的,而且不应该很复杂。

【问题讨论】:

    标签: graphql graphql-js graphql-php


    【解决方案1】:

    几个点。

    设计架构的首选方式如下:

    type Query {
      parkingLots(where: ParkingLotFilter)
    }
    
    input ParkingLotFilter {
      isFull: Boolean
      # other conditions
    }
    

    虽然您可以将 occupied 参数添加到 spots,但在提供该参数时让 parkingLots 查询仅返回具有空闲停车位的停车场是非常不直观的。如果我指定该参数,我希望得到所有个停车场,每个停车场的spots 字段仅限于被/未被占用的位置。换句话说,一个字段的过滤器应该只影响该字段的分辨率,而不是父字段的分辨率。

    这将我们带到第二点 - 您的问题可以简单地在客户端解决。在spots 上公开occupied 参数并保留它可能就足够了。然后,客户端将获得一个停车场列表,其中一些可能有一个空数组用于spots 字段。然后,客户端可以根据spots 字段的长度过滤停车场列表,以获取已满或未满的停车场列表。

    如果这不可接受,那么处理此问题的最简单方法是按照您的建议进行连接。这样做并没有什么“不符合 GraphQL 的精神”——许多工具,如 join-monsterpostgraphile 都采用了相同的方法。通过使用连接,您可以获得每个停车场的位置,并将它们作为在解析器中返回的停车场对象的一部分返回。只要对象具有spots 属性,该属性的值就会用于解析spots 字段(前提是您不编写自己的解析器)。

    【讨论】:

      猜你喜欢
      • 2019-07-15
      • 2018-10-21
      • 1970-01-01
      • 2018-07-01
      • 2019-03-28
      • 2020-04-24
      • 2018-07-07
      • 2019-07-20
      • 1970-01-01
      相关资源
      最近更新 更多