将GraphQL与条件相关类型一起使用

时间:2018-12-29 00:06:00

标签: graphql graphql-js apollo-server

我有一个应用程序,该应用程序具有许多相关类型。就像这样:

type Person {
  Name: String!
  Address: Address!
  Family: [Person!]!
  Friends: [Person!]!
  Job: Occupation
  Car: Car
}
type Address {...}
type Occupation {...}
type Car {...}

(不必担心具体类型...)

无论如何,这些都存储在数据库的许多表中。

其中一些查询很少使用且速度很慢。举例来说,假设世界上有数十亿辆汽车,并且花时间寻找我们感兴趣的人拥有的汽车。对“ getPerson”的任何查询都必须满足完整的架构,然后graphql会将其缩减为必填字段。但是由于那很慢并且可以请求 ,所以即使数据大部分时间被丢弃,我们也必须执行查询。

我只看到2种解决方案。

a)每次都执行查询,它总是很慢

b)设置2个独立的查询选项。一个用于“ getPerson”,一个用于“ getPersonWithCar”,但随后您将无法重用该架构,现在Person被定义了两次。一次就汽车而言,一次就没有汽车。

是否有一种方法可以指示在Query请求的字段中是否存在某个字段?这样我们就可以说

if (query.isPresent("Car")) {
  car = findCar();
} else {
  car = null;
}

1 个答案:

答案 0 :(得分:0)

如果您的存储层是关系数据库,则通常有两种方法来处理模式中的关系,每种方法各有利弊。一种方法是简单地让每个“关系”字段从适当的表中获取数据。因此,给定这样的Query类型:

type Query {
  getPerson: Person
}

getPerson的解析器仅从数据库中的persons表中提取一行。然后,family字段的解析程序将获取该关系的相关行,friends的解析程序将获取那些相关行,依此类推。

很明显,这可以迅速增加每个请求您要进行的数据库调用的数量,并且由于某些查询将顺序而不是并行进行,因此会影响性能。另一方面,如果不请求这些字段,则决不会调用解析器。此解决方案通常更适合其他数据源,例如从其他API提取数据,但在某些情况下仍可以加快查询速度。

另一种方法是在getUser的解析器中获取所需的所有内容。当然,获取所有可能的关系将是昂贵的,并且可能是不必要的。幸运的是,在GraphQL.js中,传递给解析器的fourth paramete r是一个“信息”对象,用于描述整个GraphQL请求。您可以解析该对象以确定请求哪些字段,并相应地微调数据库查询(或ORM方法调用)。

有一篇不错的文章here,介绍了信息对象本身的结构以及如何解析它。对此进行更深入的讨论可能超出了此问题的范围。如果您不想自己解析信息对象,则有许多可用的软件包可以为您完成工作(我推荐的软件包是graphql-parse-resolve-info)。