GraphQL:利用内省功能进行数据突变

时间:2017-01-15 02:12:55

标签: graphql introspection

根据我的理解,GraphQL是一种很好的查询语言,用于获取数据。但是,即使使用诸如Relay之类的GraphQL客户端框架,数据突变似乎也不是客户端开发人员友好的。原因是,他们需要知道变异背后的逻辑并在客户端代码中使用它。 如果GraphQL可以通过内省功能向Relay公开一些信息会更好吗,因为没有其他框架似乎已经这样做了吗?此外,以这种方式构建GraphQL客户端会遇到哪些技术挑战?

1 个答案:

答案 0 :(得分:2)

GraphQL选择在纯粹的RPC风格模型中实现突变。也就是说,突变不包括任何有关它们可能对后端进行哪些更改的元数据。相比之下,我们可以看看像REST这样的东西,其中像POST和PATCH这样的动词表明了客户对后端会发生什么的意图。

这有利有弊。一方面,如果您的框架可以学习自动合并更改,那么编写客户端代码会更方便,但是我认为除了最原则的REST API之外,这是不可能的。另一方面,RPC模型具有巨大的优势,因为服务器不限于它可以执行的操作类型。您只需编写服务器代码,就可以简单地定义您喜欢的任何语义操作,而不需要根据对特定对象的更新来描述修改。

这是否与GraphQL的其余部分一致?

我认为当前的突变实现与GraphQL设计的数据提取是一致的,它具有类似的概念:任何对象上的任何字段都可以从其他对象计算,这意味着没有稳定的概念“对象“在查询的输出中。因此,为了获得自动更新查询结果的突变,您需要考虑计算字段,参数,聚合等。当前指定的GraphQL似乎明确地权衡了它对于从服务器是有损的,以便在服务器端字段的实现中实现完全的灵活性。

是否有一些可以自动合并的突变?

是。特别是,如果您的突变返回值包含与查询相同的对象类型,则智能GraphQL客户端(如Apollo Client)会将这些结果合并到缓存中,而无需任何额外的工作。通过使用片段并为突变选择方便的返回类型,您可以通过这种方法获得大多数或所有突变:

fragment PostDetails {
  id
  score
  title
}

query PostWithDetails {
  post(id: 5) {
    ...PostDetails
  }
}

mutation UpdatePostTitle {
  updatePostTitle(id: 5, newTitle: "Great new title") {
    ...PostDetails
  }
}

事情变得棘手的地方是插入和删除对象的突变,因为它不能立即清楚客户端应该对该突变结果做些什么。

可以通过内省或其他方式改进吗?

如果保留升级到更灵活方法的能力,那么对于更加自动运行的突变限制模型是非常有利的。

一个特别的例子是使用语义方式来声明“删除”突变:

type Mutation {
  deletePost(id: ID!): DeletePostResult @deletes
}

如果客户端可以通过内省读取这些变异字段的指令,那么它可以识别deletes指令并猜测id字段表示已删除的对象,应该从该对象中清除高速缓存中。

我是Apollo的核心贡献者之一,我认为在配套包中尝试这样的功能会非常容易。我们在核心中也有一些这样的暗示,并故意设计商店格式以使这样的事情成为可能。

TL; DR

目前的方法使GraphQL非常灵活,并且与设计的其余部分保持一致,但添加约定以自动生成一些突变会很有趣。