概述
让我们回到如何连接数据之间的难题子图. 我们将处理架构中缺少的部分之一: Review.location
字段.
在本课中,我们将
- 学习如何在 子图 中将 实体 作为返回类型进行引用,方法是实现
Review.location
字段
将 Location
实体作为返回类型
我们希望使用 Location
实体 作为 Review.location
字段 的返回类型,所以让我们仔细看看如何做到这一点。
✏️ 将 Review.location
字段添加到架构中
打开
subgraph-reviews/reviews.graphql
文件。让我们添加一个新的 字段,名为
location
,它应该返回一个Location
类型。subgraph-reviews/reviews.graphqltype 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!}我们可以测试我们的更改,并在
reviews
子图 中打开 Sandbox,地址为 https://127.0.0.1:4002. 我们应该看到新的location
字段 在latestReviews
下显示。studio.apollographql.com/sandbox/explorer让我们尝试运行一个 查询 来测试我们新的 字段. 我们将查询
latestReviews
,并包括id
、comment
和rating
字段. 接下来,我们将包括新的location
字段 及其id
. 让我们还给 操作 一个描述性名称:GetLatestReviewsAndLocations
。query GetLatestReviewsAndLocations {latestReviews {idcommentratinglocation {id}}}
当我们提交 查询 时,我们可以看到我们获得了 null
作为每个 location
的值!
这是因为我们尚未定义当查询此 字段 时,reviews
子图 应该返回什么!我们首先需要定义一个相应的 解析器 函数。
✏️ Review.location
解析器函数
正如我们之前看到的,路由器 将向 reviews
子图 请求 location 的评论所关联的 实体 表示形式。 路由器 已经知道如何检索类型名称,但它需要位置的 id 键 字段. 让我们设置一下。
打开
subgraph-reviews/resolvers.js
文件。在
resolvers
对象中,我们将为Review
类型添加一个新键,以及一个为空的 解析器 函数,用于location
字段。subgraph-reviews/resolvers.jsconst resolvers = {// ...Review: {location: () => {// TODO},},};将 解析器 函数的第一个参数命名为
review
,它是 字段 的parent
对象。subgraph-reviews/resolvers.jslocation: (review) => {// TODO},对于 解析器 的主体,我们需要返回一个带有位置 id 的 实体 表示形式。那么我们如何为特定评论检索位置的 id 呢?
为了回答这个问题,我们将快速绕道看看我们从 数据源 获取的评论数据是什么。跳转到
reviews_data.json
文件,它位于datasources
目录中。在这里我们可以看到,对于每个评论对象,我们都存储了每个评论所属的locationId
。subgraph-reviews/datasources/reviews_data.json{"id": "rev-1","locationId": "loc-1","rating": 5,"comment": "..."}这个
locationId
字段 精确地指定了我们正在寻找的数据 - 位置的id
!回到
Reviews.location
解析器 中,让我们解构review
对象并提取locationId
. 然后我们将返回一个新对象,它将locationId
重新分配为id
. 这将它与Location
实体 的@key
字段 的名称匹配。subgraph-reviews/resolvers.jslocation: ({locationId}) => {return {id: locationId};},
检查你的工作
太棒了!现在让我们检查一下所有东西是否正常运行。返回到 Apollo Sandbox 查看 reviews
子图,地址是 https://127.0.0.1:4002。
让我们再次尝试执行 查询。这次,我们获得了每个地点的 ID!
query GetLatestReviewsAndLocations {latestReviews {idcommentratinglocation {id}}}
响应的形状应与以下对象匹配
现在,我们的 reviews
子图 可以解析地点的 id
字段,这正是 路由器 在跨 子图 关联数据时所需的。
要解析 其余 的 Location
字段(例如 name
、description
或 photo
),我们还需要在模式中添加一项: Location
实体 的 引用解析器!
✏️ 实现 __resolveReference
解析器
切换到
subgraph-locations
目录,打开resolvers.js
文件。在
resolvers
对象中,为Location
添加一个新键,然后添加一个 解析器 函数,名为__resolveReference
。subgraph-locations/resolvers.jsconst resolvers = {Query: {// ...},Location: {__resolveReference: () => {// TODO},},};接下来,让我们设置此函数的 参数。
解构第一个 参数,它是 实体 表示对象,并从中提取
id
字段。同样,解构第二个 参数(
context
)以访问dataSources
属性。subgraph-locations/resolvers.js__resolveReference: ({id}, {dataSources}) => {// TODO},引用 解析器 函数的主体需要返回所有 实体 字段,这些字段由此 子图 定义。为此,我们将使用
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 {idcommentratinglocation {name}}}
注意: 如果你在 location
下方看到红色波浪线 字段 上的 latestReviews
,尝试刷新页面。你可能比 超级图 组合 更快!
我们可以看到我们所有的数据都来自 locations
和 reviews
子图!
我们应该看到这样的响应
让我们更新我们的模式协议清单,并勾选我们刚刚添加到 Review 类型中的 location 字段。
练习
__resolveReference
函数接受的参数之一?关键要点
- 我们可以 引用 一个 实体 在一个 子图 中,作为类型 字段 的返回值。
- 任何对 实体 有贡献 字段 的 子图 需要为该 实体 定义一个
__resolveReference
解析器 函数。当 路由器 需要解析从其他 子图 中对该实体的引用时,就会调用这个解析器。
接下来
很棒的工作!我们的 子图 不再那么孤立了。我们也快完成检查模式协议中的 字段 了。在下节课中,我们将贡献最后两个字段: reviewsForLocation
和 overallRating
。
分享你关于本节课的问题和评论
你的反馈将帮助我们改进!如果你卡住了或感到困惑,请告诉我们,我们会帮助你。所有评论都是公开的,必须遵守 Apollo 行为准则。请注意,已解决或已处理的评论可能会被删除。
你需要一个 GitHub 帐户才能在下面发布。没有帐户? 请在我们的 Odyssey 论坛中发布。