首页 > 解决方案 > GraphQL 突变如何知道它正在修改哪个节点?数据库中的每个节点是否有唯一的全局节点 ID?

问题描述

我正在通过 Robin Wieruch 的有用教程(https://www.robinwieruch.de/getting-started-github-graphql-api/)学习 GraphQL

我不清楚的一件事是特定端点的突变如何“知道”它正在修改的对象(查询似乎通过从上到下遍历数据库树来工作)。

例如,使用 GitHub GraphQL APIaddReaction突变(https://developer.github.com/v4/mutation/addreaction/),我们有subjectID,文档说是“要修改的主题的节点 ID。”。好的,但大概在整个 GitHub 中可能有不止一件事情需要人们添加反应。这是否意味着这subjectID在整个 GitHub 中是独一无二的,因此 GraphQL API 会“自动”知道在 GitHub 的所有元素中应该添加(例如)“竖起大拇指”的确切位置?如果不是这样,它怎么知道?如果是这样,这个唯一的全局 ID 是否永久存在,直到节点被删除?

标签: reactjsgraphql

解决方案


GitHub 的 GraphQL 模式是Relay-compliant。从他们的主页:

Relay 是一个 JavaScript 框架,用于构建由 GraphQL 支持的数据驱动的 React 应用程序,从一开始就设计为易于使用、可扩展且最重要的是高性能。

虽然 Relay 是一个前端客户端,但它需要模式包含某些功能才能使客户端按预期工作。这些功能之一是全局对象识别。如何提供全局唯一的 id 由服务器决定。但是,Relay 提供了一个具有内置机制的服务器端帮助程序库:

export function toGlobalId(type: string, id: string): string {
  return base64([type, id].join(':'));
}

export function fromGlobalId(globalId: string): ResolvedGlobalId {
  const unbasedGlobalId = unbase64(globalId);
  const delimiterPos = unbasedGlobalId.indexOf(':');
  return {
    type: unbasedGlobalId.substring(0, delimiterPos),
    id: unbasedGlobalId.substring(delimiterPos + 1),
  };
}

所有这一切都是结合 id 和 GraphQL 类型,然后使用 Base64 对其进行编码。只要您不将不同表中的行作为相同类型返回,就可以保证是唯一的。

这就是 GitHub 的 API 的工作原理。但是,并非所有 GraphQL API 都符合 Relay。以这种方式设计架构既有好处也有成本。为了更直接地回答您的问题,如何解析字段完全取决于服务器。您为特定字段(包括根级突变)编写的解析器会传入几条信息:

  • 父字段解析为的值
  • 字段的参数

大多数实现还提供了某种context对象和info描述 GraphQL 请求本身的对象,尽管这不是严格的规范的一部分。关键是,这就是解析器真正“意识到”的全部。但是,由于您是编写解析器的人,因此您知道需要根据您正在为其编写解析器的字段查询或操作哪些数据。


推荐阅读