7. 引入了实体
15m

概述

是见证联合真正力量的时候了;我们将拼凑各个部分,让我们的查询比以前更加强大且动态。

在此课程中,我们将

  • 学习什么类型是,它用于什么以及如何定义它
  • Listing类型转换为

评论和列表

还记得我们梦想的 吗?

query GetListingAndReviews {
listing(id: "listing-1") {
title
description
numOfBeds
amenities {
name
category
}
overallRating
reviews {
id
text
}
}
}

正如 所示,我们希望 reviewsoverallRatingListing类型。

此方法存在的一个很大的问题是:如上所述,reviews listings 中的类型一无所知,更不用说存在一个 Listing 类型,你应该为其添加 !让我们通过实体解决这个问题。

实体是什么?

一个 实体是一个 ,它的 分布在多个 中。它是联邦图架构的基础构建模块,用于连接子图之间的数据,同时仍然遵守关注点分离原则。

在使用 时,每个 都可以执行以下一项或这两项操作:

  • 提供提供不同的
  • 引用一个 ,这意味着将其用作 中定义的另一个 的返回类型

提供与引用

要区分 贡献引用的方式:一个 贡献 实际上是从 自己的域类型中添加新数据功能。

这与一个仅仅 引用 形成对比;它本质上只是“提及”实体的存在,并将其作为 另一个字段的返回类型提供。

在联合中,我们使用实体创建统一类型,而不局限于一个 或另一个;相反,它们可以跨越我们整个 API!

在我们的例子中,我们希望以评论相关数据补充我们的 Listing类型。这使 Listing类型成为成为 的理想候选;它需要具有 在我们的 两个 中进行定义。这使我们能够构建我们 API 中“列表”的更强大的表示,以及其组成的不同数据。

要创建 ,一个 需要提供两样东西: 主键引用解析器

定义主键

实体的是能唯一标识该在一个中的实例的(或字段)。就像在数据库中一样,这些信息让我们能够区分一个事物另一个事物。当我们讨论列表时,我们使用它们的id 来识别哪个列表是我们正在讨论的。

使用主键从多个收集数据并将其与单个实例相关联。这样,我们就知道每个子图都在谈论——并提供数据给——同一个对象!

Illustration showing three entities with unique ids

我们使用@key 以及一个名为fields的属性来设置,我们要将此用作的主键。

实体语法
type EntityType @key(fields: "id") {
# ...
}

引用解析器和实体表示

由于 可以跨多个 分布,因此每个 提供 的子图都需要一种方法来标识 收集数据所针对的实例。当能够标识此实例时,便可提供更多数据。标识 的特定实例需采用称为 引用解析器的方法。

此方法会接收称为 表示形式的基本对象。 实体表示形式用于标识特定 实例的对象。表示形式包含用于该 类型名以及特定实例的 @key

  • __typename 字段:此 在所有 类型中自动存在。它始终以字符串形式返回其包含类型的名称。例如, Listing.__typename返回 “Listing”。

  • @key 字段: 可用于识别实例的一个键值对。例如,如果我们使用“id”作为主键定义了Listing ,那么我们的实体表示将包含一个“id”属性,其值类似于“listing-3”。

针对特定解析时,它会将表示传递给每个,如下所示:

Listing 实体表示示例
{
"__typename": "Listing",
"id": "listing-3"
}

您可以将表示视作关联来自多个的数据时所需的最低基本信息,并确保每个子图都是针对同一对象进行讨论的。

正如我们很快就会看到的,特定房源的表示将向我们的 提供所需的所有信息(不多不少!),以提供相关评论数据。

创建Listing实体

回到我们的梦想!我们希望让Listing类型成为,以便reviews 可以向其中添加两个overallRatingreviews

让我们开始吧!

listings 子图中

rover dev进程仍在运行的情况下,打开listings 并导航至schema.graphql。向下滚动找到Listing类型。

这里,我们将应用@key ,传递一个fields属性,设置为"id"

(listings) schema.graphql
type Listing @key(fields: "id") {
id: ID!
# ... other Listing fields
}

在保存更改后,rover dev将自动获取新架构并重新启动进程。在转到reviews 之前,请确保它成功构图了。

reviews 子图中

打开代码编辑器转到 reviews ,然后导航到 src/schema.graphql 文件。我们首先通过添加 Listing 类型的基本存根来开始:它由类型名、 @key 和指定为主键的 id 组成。

(reviews) schema.graphql
type Listing @key(fields: "id") {
id: ID!
}

请注意,我们不包含 其他任何 ,它们来自 Listing ,如

让我们将该 reviews 添加到 Listing 类型中。我们为它指定 [Review!]! 的返回类型。我们还定义了 ,它返回一种可为空的 类型。

(reviews) schema.graphql
type Listing @key(fields: "id") {
id: ID!
"The submitted reviews for this listing"
reviews: [Review!]!
"The overall calculated rating for a listing"
overallRating: Float
}

测试我们的架构更改

我们的 rover dev 进程仍应在运行,因此让我们跳回到 https://127.0.0.1:4002

现在我们将看到 reviews 可在 Listing 类型下使用。我们小巧的架构变更使得构建我们的理想 成为可能!

https://127.0.0.1:4002

Sandbox with our dream query syntax written into the Operation panel

query GetListingAndReviews {
listing(id: "listing-1") {
title
description
numOfBeds
amenities {
name
category
}
overallRating
reviews {
id
text
}
}
}

虽然我们的 看起来很漂亮,但实际上不能返回数据。尽管 listings 可以轻松解析 自己 listing (idtitledescriptionnumOfBeds 以及 amenities),但我们尚未告知 reviews 何时执行 请求特定 listing 的 reviewsoverallRating

事实上,如果我们运行 ,只会看到一堆可怕的错误。

练习

检验你的理解情况!
实体的主键用于识别 内该实体的一个唯一实例。
 
要定义一个主键,应用 
 
 指令,并将主键字段的名称作为 的 属性值传递。
 
一个实体可以有 个主键。
 
 

将此框中的内容拖动到上面的空白处

  • 路由器

  • 多个

  • 字段

  • 只能一个

  • 子图

  • @unique

  • @key

  • 引用解析器

  • @primary

要点

  • 实体解析其的类型。
  • 若要创建,可使用@key 指定哪些可以唯一标识该类型的一个对象。
  • 可以使用实体的两种方式
    • 作为的返回类型(引用)。
    • 定义来自多个(为实体做出贡献)。

接下来

在下一课中,我们将为reviews 配备逻辑,以便实际返回数据。

上一页

分享你对本课的疑问和评论

本课程当前处于

测试版
.你的反馈有助于我们改进!如果遇到了困难或困惑的问题,请联系我们,我们会向你提供帮助。所有评论都是公开的,并且必须遵循 阿波罗行为准则。请注意,已经解决或已处理的评论可能会被删除。

你需要一个 GitHub 帐户才能在下方发帖。没有帐户? 转而到我们的 Odyssey 论坛发帖。