9. 查询参数
10m

概述

我们现在可以 我们 REST API 中的数据,但只能查询 featuredListings。让我们为我们的 功能添加另一个选项!

在本课中,我们将

  • 探索
  • 添加一个新的 Query 类型
  • 传递到

介绍查询参数

是时候为我们的 Query 类型添加另一个入口点,以及一个新的 API 功能!

虽然我们可以从 REST API 获取特色列表,但我们还没有办法请求 特定 列表的详细信息。这个单一的 Query 入口点无法满足我们所有模型的需求;我们的 Listing 类型仍然缺少一些 来保存其描述和便利设施!

A screenshot of a single listing in Airlock, focused on two additional required fields

查询 /listings/{listing_id} 终端

让我们回到我们的列表 REST API 终端。到目前为止,我们只探索了 GET /featured-listings 终端,但我们还有另一个选项可用于获取特定列表的数据: GET /listings/{listing_id}

我们可以使用此链接 来请求特定列表。(注意,我们已经传递了值 listing-1 代替 {listing_id}!)

GET /listings/{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
]
}

这里有我们所需的一切(以及一些我们很快就会使用到的其他属性)!

为了将此功能引入我们的 API,我们需要在我们的模式中添加另一个入口点。我们将能够指定 哪个 唯一的列表我们正在 ,通过为这个 提供一个 参数

🤔 如何使用参数

一个 是您为查询中的特定 提供的值。模式定义了每个字段接受的参数。

然后,您的数据获取器可以使用 提供的 来帮助确定如何填充该字段的数据。参数可以帮助您检索特定对象、过滤一组对象,甚至转换字段的返回值。执行搜索的 通常将用户的搜索词作为参数提供。

要为模式中的 定义一个 ,我们在字段名称后添加括号。在括号内,我们编写参数名称,后跟冒号,然后是该参数的类型,例如 StringInt。如果我们有多个 ,我们可以用逗号隔开它们。

添加 listing 字段

打开 schema.graphqls 文件,并将以下 添加到 Query 类型。

schema.graphqls
listing: Listing

我们将为 提供一个描述,然后在 listing 后添加括号以指定其 id,类型为 ID!

schema.graphqls
"Returns the details about this listing"
listing(id: ID!): Listing

这就是 定义!现在我们的模式已经为我们正在实现的功能更新好了。接下来是我们的 ListingService:让我们添加一个新方法来访问此终端!

更新 ListingService

回到 datasources/ListingService 中,我们将创建一个名为 listingRequest 的新方法,该方法可以管理对特定列表终端的调用。它将接收一个 String 类型 称为 listingId,并返回一个 ListingModel 实例。

datasources/ListingService
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 注解。

datafetchers/ListingDataFetcher
// ...featuredListings method
@DgsQuery
public ListingModel listing() {}

当我们 我们的 API 来获取 listing 时,我们传递的 id 会自动传递到这个数据提取器。(记住,方法的名称,listing,需要与其对应的 Query 完全匹配!)

为了接收它,并真正利用它,我们将指定它接收一个类型为 Stringid

@DgsQuery
public ListingModel listing(String id) {}

为了明确这个参数对应于我们在模式的 listing 中指定的 id 输入,我们需要添加一个特定的 DGS 注解,称为 @InputArgument

让我们导入它...

import com.netflix.graphql.dgs.InputArgument;

... 并更新我们的方法。

public ListingModel listing(@InputArgument String id) {}

现在我们可以调用 ListingService 上的新的 listingRequest 方法!在 listing 方法中,我们将传入 id 并返回结果。

@DgsQuery
public ListingModel listing(@InputArgument String id) {
return listingService.listingRequest(id);
}

让我们测试一下!重启你的服务器,然后返回到 Explorer 来写一个新的

任务!

测试 listing 字段

文档 面板中,我们会看到我们的 Query 类型包含了我们新的 listing 。当我们点击它时,我们甚至可以查看它接收的 的名称和类型。让我们添加一个新的工作区选项卡,然后点击 listing 旁边的加号按钮,将其添加到我们的 中。

Explorer 会自动插入一些语法来帮助我们更容易地完成

https://studio.apollographql.com/sandbox/explorer

The Explorer Operation panel, filled in with the listing operation and some additional syntax for the variable

让我们将我们的 更新为 GetListing,以便更清楚地说明我们正在对请求的数据执行的操作。

query GetListing($listingId: ID!) {
listing(id: $listingId) {
}
}

你将会注意到这里出现了一些新的东西:一个美元符号($)后面跟着名称 listingId

$ 符号表示一个 中。 $ 符号后面的名称是我们 的名称,我们可以在整个 中使用它。冒号后面的则是变量的类型,它必须与我们将它用于的 的类型相匹配。变量很棒,它们让我们能够从客户端动态地传递参数值,这样我们就不必在查询中硬编码值。我们每次创建具有参数的查询时都会使用它们。

在我们的例子中,我们有一个名为 listingId,Explorer 为我们设置了它,它位于 变量 部分。现在,它被设置为 null,但是让我们用我们一直在测试的房源 ID 来替换它:listing-1

将以下内容添加到 Explorer 中的 变量 部分:

{ "listingId": "listing-1" }

让我们通过添加几个更多的 来测试我们的 ,这些字段用于我们所要查找的房源:titlenumOfBeds

https://studio.apollographql.com/sandbox/explorer

The Explorer Operation panel, with a query for a particular listing's title and number of beds, along with the listing ID variable

Explorer 的 操作 面板现在应该看起来像这样:

query GetListing($listingId: ID!) {
listing(id: $listingId) {
title
numOfBeds
}
}

当我们点击运行 按钮时,我们会看到我们期望的数据!

这很有效,但我们仍然缺少几个 来完成我们对单个房源的模拟。当我们检查房源的 REST API 响应时,我们会看到每个房源 JSON 对象都包含一个 "description" 键;所以让我们继续更新我们的 Listing 类型以包含它。

回到 schema.graphqls 中,添加下面显示的 description

schema.graphqls
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

但我们对模拟中显示的便利设施列表呢?

A screenshot of a single listing in Airlock, focused on two additional required fields

我们仍然缺少关于每个便利设施的数据,甚至在我们的 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 的问题。

练习

我们在哪里可以向我们的模式添加入口点?
以下哪些是使用查询参数的原因?
变量
变量用 
 
符号表示。它们用于为 
 
提供动态值,以避免在查询中包含 
 
 值。每个变量的类型必须与在 
 

将此框中的项目拖动到上面的空白处

  • 图表

  • 硬编码

  • 参数

  • !

  • 模式

  • @

  • $

  • 数据获取器

  • 名称

关键要点

  • 允许我们过滤、自定义和进一步指定我们想要查询的数据。
  • 我们可以参考 直接传递到 使用 DGS @InputArgument 注解。
  • 我们可以在 Explorer 中使用 $ 符号来指定

下一步

在下一课中,我们将探索如何构建 之间的关联,特别是我们的 Listing 类型和一个新类型(我们将称之为 Amenity)。

上一页

分享您关于本课的疑问和评论

本课程目前处于

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

您需要一个 GitHub 帐户才能在下面发帖。没有账号? 在我们的 Odyssey 论坛上发帖。