GraphQL 过滤子解析器中的父数据

hor*_*tiu 7 graphql graphql-js graphql-php

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

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

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

type ParkingSpot {
  id: Int!,
  occupied: Boolean!
}
Run Code Online (Sandbox Code Playgroud)

我想以一种使我能够检索所有至少有一个免费停车位的停车场的方式实现我的解析器。

query AllParkingLotsWithStatus($status : Boolean = false) {
   ParkingLot {
     id 
     spots(occupied: $status)  {
       id
     }
   }
}
Run Code Online (Sandbox Code Playgroud)

我正在使用的 GraphQL 的具体实现是基于 PHP 的,可在此处获得但任何基于 JS 的实现都非常有助于为我指明正确的方向。我知道有一些库支持使用“where:”参数进行过滤,但我必须自己实现这种机制,因为我使用的库没有提供开箱即用的功能。

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

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

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

Dan*_*den 2

有几点。

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

type Query {
  parkingLots(where: ParkingLotFilter)
}

input ParkingLotFilter {
  isFull: Boolean
  # other conditions
}
Run Code Online (Sandbox Code Playgroud)

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

这就引出了第二点——您的问题可以简单地在客户端解决。occupied揭露争论spots并就此结束可能就足够了。然后,客户端将获得停车场列表,其中一些停车场可能有一个空数组spots。然后,客户端可以根据字段的长度过滤停车场列表,spots以获得已满或未满的停车场列表。

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