12. 引用实体
5m

概述

让我们回到如何连接数据之间的难题. 我们将处理架构中缺少的部分之一: Review.location .

在本课中,我们将

  • 学习如何在 中将 作为返回类型进行引用,方法是实现 Review.location
The FlyBy schema diagram, with a pencil icon next to the Review.location field

Location 实体作为返回类型

我们希望使用 Location 作为 Review.location 的返回类型,所以让我们仔细看看如何做到这一点。

✏️Review.location 字段添加到架构中

  1. 打开 subgraph-reviews/reviews.graphql 文件。

  2. 让我们添加一个新的 ,名为 location,它应该返回一个 Location 类型。

    subgraph-reviews/reviews.graphql
    type Review {
    id: ID!
    "Written text"
    comment: String
    "A number from 1 - 5 with 1 being lowest and 5 being highest"
    rating: Int
    "The location the review is about"
    location: Location
    }
    type Location @key(fields: "id", resolvable: false) {
    id: ID!
    }
  3. 我们可以测试我们的更改,并在 reviews 中打开 Sandbox,地址为 https://127.0.0.1:4002. 我们应该看到新的 location latestReviews 下显示。

    studio.apollographql.com/sandbox/explorer
    The Sandbox Explorer page of GraphOS Studio
  4. 让我们尝试运行一个 来测试我们新的 . 我们将查询 latestReviews,并包括 idcommentrating . 接下来,我们将包括新的 location 及其 id. 让我们还给 一个描述性名称: GetLatestReviewsAndLocations

    query GetLatestReviewsAndLocations {
    latestReviews {
    id
    comment
    rating
    location {
    id
    }
    }
    }

当我们提交 时,我们可以看到我们获得了 null 作为每个 location 的值!

这是因为我们尚未定义当查询此 时,reviews 应该返回什么!我们首先需要定义一个相应的 函数。

✏️ Review.location 解析器函数

正如我们之前看到的, 将向 reviews 请求 location 的评论所关联的 表示形式。 已经知道如何检索类型名称,但它需要位置的 id 键 . 让我们设置一下。

  1. 打开 subgraph-reviews/resolvers.js 文件。

  2. resolvers 对象中,我们将为 Review 类型添加一个新键,以及一个为空的 函数,用于 location

    subgraph-reviews/resolvers.js
    const resolvers = {
    // ...
    Review: {
    location: () => {
    // TODO
    },
    },
    };
  3. 函数的第一个参数命名为 review,它是 parent 对象。

    subgraph-reviews/resolvers.js
    location: (review) => {
    // TODO
    },
  4. 对于 的主体,我们需要返回一个带有位置 id 的 表示形式。那么我们如何为特定评论检索位置的 id 呢?

    为了回答这个问题,我们将快速绕道看看我们从 获取的评论数据是什么。跳转到 reviews_data.json 文件,它位于 datasources 目录中。在这里我们可以看到,对于每个评论对象,我们都存储了每个评论所属的 locationId

    subgraph-reviews/datasources/reviews_data.json
    {
    "id": "rev-1",
    "locationId": "loc-1",
    "rating": 5,
    "comment": "..."
    }

    这个 locationId 精确地指定了我们正在寻找的数据 - 位置的 id

  5. 回到 Reviews.location 中,让我们解构 review 对象并提取 locationId. 然后我们将返回一个新对象,它将 locationId 重新分配为 id. 这将它与 Location @key 的名称匹配。

    subgraph-reviews/resolvers.js
    location: ({locationId}) => {
    return {id: locationId};
    },

检查你的工作

太棒了!现在让我们检查一下所有东西是否正常运行。返回到 查看 reviews ,地址是 https://127.0.0.1:4002

让我们再次尝试执行 。这次,我们获得了每个地点的 ID!

query GetLatestReviewsAndLocations {
latestReviews {
id
comment
rating
location {
id
}
}
}

响应的形状应与以下对象匹配

现在,我们的 reviews 可以解析地点的 id ,这正是 在跨 关联数据时所需的。

要解析 其余Location (例如 namedescriptionphoto),我们还需要在模式中添加一项: Location 引用解析器

✏️ 实现 __resolveReference 解析器

  1. 切换到 subgraph-locations 目录,打开 resolvers.js 文件。

  2. resolvers 对象中,为 Location 添加一个新键,然后添加一个 函数,名为 __resolveReference

    subgraph-locations/resolvers.js
    const resolvers = {
    Query: {
    // ...
    },
    Location: {
    __resolveReference: () => {
    // TODO
    },
    },
    };
  3. 接下来,让我们设置此函数的

    解构第一个 ,它是 表示对象,并从中提取 id

    同样,解构第二个 context)以访问 dataSources 属性。

    subgraph-locations/resolvers.js
    __resolveReference: ({id}, {dataSources}) => {
    // TODO
    },
  4. 引用 函数的主体需要返回所有 ,这些字段由此 定义。为此,我们将使用 LocationsAPI 及其 getLocation 方法。它返回给定 ID 的 Location 对象。

    subgraph-locations/resolvers.js
    __resolveReference: ({id}, {dataSources}) => {
    return dataSources.locationsAPI.getLocation(id);
    },

    注意:你可以查看 getLocation 方法是如何工作的,方法是查看 subgraph-locations/datasources/LocationsApi.js 文件。

就这样,我们的 现在已完全设置好,可以处理引用实体了!

好的,我们应该准备好在 Studio 中 我们的 超级图,并观察 在我们的 之间关联数据的魔力!

让我们开始构建 GetLatestReviews ,我们之前已经与前端团队达成一致。我们将添加我们的 ……等等,我们的 location 去哪里了?它不是在 Sandbox 上本地运行得很好吗?发生了什么事?

我们忘记发布我们的 reviews 的更改到注册表了!

✏️ 使用 Rover 发布子图更改

哎呀!让我们跳到项目根目录下的终端,运行 rover subgraph publish,传入 用于 reviews

rover subgraph publish <APOLLO_GRAPH_REF> \
--name reviews \
--schema ./subgraph-reviews/reviews.graphql

现在我们应该可以准备好在 Studio 中查询我们的超级图,并观察路由器在我们的子图之间关联数据的魔力了!

✏️ 检查你的工作是否与路由器一致

让我们在 Studio 中运行这个

query GetLatestReviews {
latestReviews {
id
comment
rating
location {
name
}
}
}

注意: 如果你在 location 下方看到红色波浪线 上的 latestReviews,尝试刷新页面。你可能比 更快!

我们可以看到我们所有的数据都来自 locationsreviews !

我们应该看到这样的响应

让我们更新我们的模式协议清单,并勾选我们刚刚添加到 Review 类型中的 location

The FlyBy schema diagram, with pencil icons next to the Location.reviews and Location.overallRating fields

练习

当子图将实体作为返回值引用时,它会提供该实体的表示形式供路由器使用。以下哪些内容包含在该表示形式中?
以下哪个不是 __resolveReference 函数接受的参数之一?

关键要点

  • 我们可以 引用 一个 在一个 中,作为类型 的返回值。
  • 任何对 有贡献 需要为该 定义一个 __resolveReference 函数。当 需要解析从其他 中对该实体的引用时,就会调用这个解析器。

接下来

很棒的工作!我们的 不再那么孤立了。我们也快完成检查模式协议中的 了。在下节课中,我们将贡献最后两个字段: reviewsForLocationoverallRating

上一节

分享你关于本节课的问题和评论

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

你需要一个 GitHub 帐户才能在下面发布。没有帐户? 请在我们的 Odyssey 论坛中发布。