9. 使用实体连接数据
7m

概述

我们的基础已经完成。我们已经将 FlyBy 的模式拆分为位置数据和评论数据,并且我们已经实现,它们只定义自己涉及的类型。

重新审视我们的模式约定清单,我们仍然有三个我们还不知道如何实现:

  • Location.reviewsForLocationLocation.overallRating:这两者都是 Location 类型中的 ,不过我们决定将这两者归属于 reviews
  • Review.location:这是 Review 类型(位于 reviews )中的 ,可是该 的返回类型为 Location,而这一类型则是在 locations 中定义的。
The FlyBy schema diagram, with the three remaining fields in focus

要实现这些 ,我们必须向开发人员工具包中添加一个新工具: 实体

在这一课中,我们将

  • 了解什么是 ,以及它的用途
  • 了解如何定义
  • 了解 间传输数据时如何表示实体

什么是实体?

实体是一种分布在多个 中的 ,包含的 在此类对象类型中呈现。

这意味着,我们可以定义一个类型,该类型 存在于我们 中,也可以对这些子图的 进行独立解析。

Illustration of 2 subgraphs contributing fieleds to an entity.

在 FlyBy 中,我们希望我们的评论包括所评论的位置。我们的 Location 类型需要同时用于 子图,因此,我们将把 Location 类型转变为

一个 (它定义了一个 )能够完成以下一个或两个操作:

  1. 引用
  2. 贡献

引用实体

引用 意味着使用它作为其他 返回类型(该字段在 内定义)。

例如,在 reviews 中,我们可以在 Review 类型中添加一个 location ,该字段会引用 Location 作为其返回类型。

The Review type, with a location field that has a return value of a Location type

向实体贡献字段

添加表示一个为实体添加特定于该子图谱专有问题的字段。

Location 将为namedescriptionphoto包含,它们都存在于locations 中。换句话说,locations 将这些添加到Location 中。

reviews 将为Location 添加两个特定于评论的reviewsForLocationoverallRating

The Location entity, with fields divided between the locations and reviews subgraph

如何创建实体

中将对象转换成,我们需要做两件事:

  1. 主键
  2. 引用解析器

定义主键

一个的主键是(或字段),它们可以唯一标识该中的一个实例。 使用主键从多个子图收集数据,并将其与单个实体实例相关联。

例如,一个位置的主键是它的 ID。 使用该 ID 收集有关特定位置实例的数据,例如 ID 为“loc-1”的位置。

Illustration showing three entities with unique ids

在我们的每个中,我们可以通过添加@key 在类型的名称后,为一个定义一个主键。

@key 需要一个称为fields的属性,我们将把它设置是我们想要用作的主键。

实体语法
type EntityType @key(fields: "id") {
id: ID!
}
Illustration showing the syntax for defining an entity. See code snippet above for an example.

定义引用解析器函数

每个 ,为 贡献 ,还需要为此实体定义一个特殊 函数,称为 引用解析器使用引用 直接访问 ,每个 都应为其做出贡献。

Illustration of each subgraph contributing fields to an entity with an associated reference resolver.

每个引用 的名称如下: __resolveReference。我们为每个 的引用 定义与该类型的所有 解析器一起使用。

__resolveReference函数的签名与其他 函数稍微不同。 __resolveReference它不是像往常一样使用四个 ,而是仅使用三个参数:

  • reference传入的表示对象。它会告诉 正在请求哪个实体实例。我们将在下面的部分中介绍实体表示是什么。
  • context:共享于所有 的对象。(这与普通解析器中相同,但请注意,按照惯例,我们将此__resolveReference 称为 context,而不是其他 中的 contextValue!)
  • info:包含有关 执行状态的信息,就像普通 一样。我们不会使用太多
Illustration of each subgraph contributing fields to an entity with an associated reference resolver.

让我们先关注这个第一个 reference,并详细了解 表述。

什么是实体表述?

一个 实体表述用来表示一个特定 实例的对象。一个表述总是包括该 类型名和特定实例的 @key

  • __typename 字段:此 存在于所有 类型上,并且自动存在。它始终以字符串的形式返回其包含类型的名称。例如, Location.__typename返回“Location”。
  • @key 字段:一个 可以用它来识别 的实例的一对键值。例如,如果我们使用"id" 作为 Location 的主键,那么我们的实体表示将包括一个"id"属性,其值类似于"loc-2"。

一个 的位置表示可能如下所示:

示例位置实体表示
{
"__typename": "Location",
"id": "loc-2"
}

您可以将 表示视为护照, 用护照来引用 之间的特定对象。

typename 就像护照的原籍国。它说明了该对象属于哪个 。并且 @key 就如同护照的 ID 号码,唯一标识该 的实例。

The representation object is like a passport

练习

实体的 __resolveReference 函数应该定义在哪里?
检查您的理解!
实体的主键用于识别 

中的该实体的唯一实例
 
要定义主键,请应用 
 
 指令,并将主键字段的名称作为 
 
 属性的值传递。一个实体可以有一个 
 
 主键。

将该框中的项拖动到上方的空白部分

  • 引用解析器

  • 子图

  • @unique

  • 字段

  • 路由

  • @key

  • 仅一个

  • 多个

  • @primary

关键要点

  • 实体是一种在其多个子图中解析其字段(s) 的类型。
  • 要创建实体,我们可以使用@key 指令指定哪个字段(s) 可以唯一标识该类型的某个对象。
  • 我们可以通过两种方式使用实体
    • 作为字段的返回类型(引用一个实体)。
    • 实体定义字段(从多个子图中贡献到实体)。
  • 所有为某个贡献需要为该实体定义一个引用函数。此__resolveReference 需要从另一个访问给定时调用。
  • 一个表示是一个对象,使用此对象来表示实体的一个具体实例。它包括实体的类型及其键

接下来

我们已经针对实体介绍了很多!在下一课中,我们将回到我们的代码中,并定义我们的第一个

前一页

分享你对本课程的问题和评论

你的反馈有助于我们改进!如果你遇到了困难或感到困惑,请告诉我们,我们会帮助你的。所有评论都是公开的,且必须遵守 Apollo 行为准则。注意,已解决或已处理的评论可能会被删除。

你需要一个 GitHub 帐户才能在下方发帖。如果没有 GitHub 帐户怎么办? 请在我们的 Odyssey 论坛中发帖。