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

时间:2019-02-20 18:03:26

标签: graphql graphql-js graphql-php

我试图弄清楚如何使用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的精神。

我想到的另一个想法是重写查询,以便它首先检索ParkingSlot,并且仅在其状态可用时才获取其父级。但是,这可能会占用大量计算资源,因为停车场的数量将少于停车位,因此从父母到孩子的关系导航可能会减少计算强度。

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

1 个答案:

答案 0 :(得分:0)

点对。

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

type Query {
  parkingLots(where: ParkingLotFilter)
}

input ParkingLotFilter {
  isFull: Boolean
  # other conditions
}

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

这使我们进入第二点-您的问题可以简单地在客户端解决。暴露occupied上的spots自变量,然后保留它就足够了。然后,客户将获得一个停车场清单,其中某些停车场的spots字段可能为空。然后,客户可以根据spots字段的长度过滤停车场清单,以获取已满或未满的停车场清单。

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