概述
我们现在可以查询 我们 REST API 中的数据,但只能查询 featuredListings
。让我们为我们的 查询 功能添加另一个选项!
在本课中,我们将
- 探索 查询 参数 在 GraphQL
- 向 字段 添加一个新的
Query
类型 - 将 变量 传递到 GraphQL 查询
介绍查询参数
是时候为我们的 Query
类型添加另一个入口点,以及一个新的 API 功能!
虽然我们可以从 REST API 获取特色列表,但我们还没有办法请求 特定 列表的详细信息。这个单一的 Query
入口点无法满足我们所有模型的需求;我们的 Listing
类型仍然缺少一些 字段 来保存其描述和便利设施!
查询 /listings/{listing_id}
终端
让我们回到我们的列表 REST API 终端。到目前为止,我们只探索了 GET /featured-listings
终端,但我们还有另一个选项可用于获取特定列表的数据: GET /listings/{listing_id}
。
我们可以使用此链接 来请求特定列表。(注意,我们已经传递了值 listing-1
代替 查询 变量, {listing_id}
!)
https://rt-airlock-services-listing.herokuapp.com/listings/listing-1
以下是一些响应中包含的属性的片段
{"id": "listing-1","title": "Cave campsite in snowy MoundiiX","description": "Enjoy this amazing cave campsite in snow MoundiiX, where you'll be one with the nature and wildlife in this wintery planet. All space survival amenities are available. We have complementary dehydrated wine upon your arrival. Check in between 34:00 and 72:00. The nearest village is 3AU away, so please plan accordingly. Recommended for extreme outdoor adventurers.",// ... more listing properties"amenities": [{"id": "am-2","category": "Accommodation Details","name": "Towel"},{"id": "am-10","category": "Space Survival","name": "Oxygen"}// ... other amenities]}
这里有我们所需的一切(以及一些我们很快就会使用到的其他属性)!
为了将此功能引入我们的 GraphQL API,我们需要在我们的模式中添加另一个入口点。我们将能够指定 哪个 唯一的列表我们正在 查询,通过为这个 字段 提供一个 参数。
🤔 如何使用参数
一个 参数 是您为查询中的特定 字段 提供的值。模式定义了每个字段接受的参数。
然后,您的数据获取器可以使用 字段 提供的 参数 来帮助确定如何填充该字段的数据。参数可以帮助您检索特定对象、过滤一组对象,甚至转换字段的返回值。执行搜索的 查询 通常将用户的搜索词作为参数提供。
要为模式中的 字段 定义一个 参数,我们在字段名称后添加括号。在括号内,我们编写参数名称,后跟冒号,然后是该参数的类型,例如 String
或 Int
。如果我们有多个 参数,我们可以用逗号隔开它们。
添加 listing
字段
打开 schema.graphqls
文件,并将以下 字段 添加到 Query
类型。
listing: Listing
我们将为 字段 提供一个描述,然后在 listing
后添加括号以指定其 参数: id
,类型为 ID!
。
"Returns the details about this listing"listing(id: ID!): Listing
这就是 查询 定义!现在我们的模式已经为我们正在实现的功能更新好了。接下来是我们的 ListingService
:让我们添加一个新方法来访问此终端!
更新 ListingService
回到 datasources/ListingService
中,我们将创建一个名为 listingRequest
的新方法,该方法可以管理对特定列表终端的调用。它将接收一个 String
类型 变量 称为 listingId
,并返回一个 ListingModel
实例。
public ListingModel listingRequest(String id) {}
此终端仍然是一个 GET
操作,我们将链接一些方法: get()
、uri()
和 retrieve()
。终端还需要一个列表 ID,因此我们将包含我们传递到此方法中的 listingId
作为 uri
的第二个参数。
public ListingModel listingRequest(String id) {return client.get().uri("/listings/{listing_id}", id).retrieve()}
最后,我们将响应映射到 ListingModel
类。
public ListingModel listingRequest(String id) {return client.get().uri("/listings/{listing_id}", id).retrieve().body(ListingModel.class);}
注意:就像我们对 featuredListingsRequest
所做的那样,我们使 listingRequest
的名称格外冗长,以避免与 ListingDataFetcher
上的 listing
方法混淆。这些是不同的方法,我们将从我们的 this listingRequest
方法调用 listing
数据获取器,很快。
在数据提取器中使用参数
现在我们可以为新的 Query.listing
字段 写数据提取器方法。
打开 datafetchers/ListingDataFetcher
。在这里,我们将在 featuredListings
之后添加一个新方法用于 listing
字段。因为这仍然是一个 Query
类型 字段,我们将使用 @DgsQuery
注解。
// ...featuredListings method@DgsQuerypublic ListingModel listing() {}
当我们 查询 我们的 GraphQL API 来获取 listing
字段 时,我们传递的 id
参数 会自动传递到这个数据提取器。(记住,方法的名称,listing
,需要与其对应的 Query
字段 完全匹配!)
为了接收它,并真正利用它,我们将指定它接收一个类型为 String
的 id
。
@DgsQuerypublic ListingModel listing(String id) {}
为了明确这个参数对应于我们在模式的 listing
字段 中指定的 id
输入,我们需要添加一个特定的 DGS 注解,称为 @InputArgument
。
让我们导入它...
import com.netflix.graphql.dgs.InputArgument;
... 并更新我们的方法。
public ListingModel listing(@InputArgument String id) {}
现在我们可以调用 ListingService
上的新的 listingRequest
方法!在 listing
方法中,我们将传入 id
参数 并返回结果。
@DgsQuerypublic ListingModel listing(@InputArgument String id) {return listingService.listingRequest(id);}
让我们测试一下!重启你的服务器,然后返回到 Explorer 来写一个新的 查询。
测试 listing
字段
在 文档 面板中,我们会看到我们的 Query
类型包含了我们新的 listing
字段。当我们点击它时,我们甚至可以查看它接收的 参数 的名称和类型。让我们添加一个新的工作区选项卡,然后点击 listing
字段 旁边的加号按钮,将其添加到我们的 查询 中。
Explorer 会自动插入一些语法来帮助我们更容易地完成 查询。
让我们将我们的 操作名称 更新为 GetListing
,以便更清楚地说明我们正在对请求的数据执行的操作。
query GetListing($listingId: ID!) {listing(id: $listingId) {}}
你将会注意到这里出现了一些新的东西:一个美元符号($
)后面跟着名称 listingId
。
在 $
符号表示一个 变量 在 GraphQL 中。 $
符号后面的名称是我们 变量 的名称,我们可以在整个 查询 中使用它。冒号后面的则是变量的类型,它必须与我们将它用于的 参数 的类型相匹配。变量很棒,它们让我们能够从客户端动态地传递参数值,这样我们就不必在查询中硬编码值。我们每次创建具有参数的查询时都会使用它们。
在我们的例子中,我们有一个名为 listingId
的 变量,Explorer 为我们设置了它,它位于 变量 部分。现在,它被设置为 null
,但是让我们用我们一直在测试的房源 ID 来替换它:listing-1
。
将以下内容添加到 Explorer 中的 变量 部分:
{ "listingId": "listing-1" }
让我们通过添加几个更多的 字段 来测试我们的 查询,这些字段用于我们所要查找的房源:title
和 numOfBeds
。
Explorer 的 操作 面板现在应该看起来像这样:
query GetListing($listingId: ID!) {listing(id: $listingId) {titlenumOfBeds}}
当我们点击运行 查询 按钮时,我们会看到我们期望的数据!
这很有效,但我们仍然缺少几个 字段 来完成我们对单个房源的模拟。当我们检查房源的 REST API 响应时,我们会看到每个房源 JSON 对象都包含一个 "description"
键;所以让我们继续更新我们的 Listing
类型以包含它。
回到 schema.graphqls
中,添加下面显示的 description
字段。
type Listing {id: ID!"The listing's title"title: String!"The listing's description"description: String!"The number of beds available"numOfBeds: Int!"The cost per night"costPerNight: Float!"Indicates whether listing is closed for bookings (on hiatus)"closedForBookings: Boolean}
我们不需要使用这个新属性来更新我们的 ListingModel
;当我们重启服务器时,我们生成的 Listing
类型会自动扩展 ListingModel
,并将配备新的 description
字段。
但我们对模拟中显示的便利设施列表呢?
我们仍然缺少关于每个便利设施的数据,甚至在我们的 JSON 响应中,它看起来比我们迄今为止探索的模式 字段 还要复杂,每个便利设施都有一个 "id"
、"name"
和 "category"
!
{"id": "listing-1",// ... other listing properties"amenities": [{"id": "am-2","category": "Accommodation Details","name": "Towel"},{"id": "am-10","category": "Space Survival","name": "Oxygen"}// ... other amenities]}
让我们在下一节课中解决将便利设施数据引入我们的 API 的问题。
练习
将此框中的项目拖动到上面的空白处
图表
硬编码
参数
!
模式
@
$
数据获取器
空
名称
关键要点
- 查询 参数 允许我们过滤、自定义和进一步指定我们想要查询的数据。
- 我们可以参考 参数 直接传递到 GraphQL 字段 使用 DGS
@InputArgument
注解。 - 我们可以在 Explorer 中使用
$
符号来指定 查询 变量。
下一步
在下一课中,我们将探索如何构建 对象类型 之间的关联,特别是我们的 Listing
GraphQL 类型和一个新类型(我们将称之为 Amenity
)。
分享您关于本课的疑问和评论
本课程目前处于
您需要一个 GitHub 帐户才能在下面发帖。没有账号? 在我们的 Odyssey 论坛上发帖。