

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# GraphQL 結構描述
<a name="schema-components"></a>

GraphQL 結構描述是 GraphQL API 的基礎。它可做為定義資料形狀的藍圖。它也是用戶端和伺服器之間的合約，定義如何擷取和/或修改您的資料。

GraphQL 結構描述是以*結構描述定義語言* (SDL) 撰寫。SDL 由具有已建立結構的類型和欄位組成：
+ **類型**：類型是 GraphQL 如何定義資料的形狀和行為。GraphQL 支援多種類型，將在本節稍後說明。結構描述中定義的每個類型都會包含自己的範圍。在範圍內，一個或多個欄位可以包含 GraphQL 服務中使用的值或邏輯。類型會填入許多不同的角色，最常見的是物件或純量 （基本值類型）。
+ **欄位**：欄位存在於 類型的範圍內，並保留從 GraphQL 服務請求的值。這些與其他程式設計語言的變數非常相似。您在欄位中定義的資料形狀將決定資料在請求/回應操作中的結構。這可讓開發人員預測傳回的內容，而不知道服務的後端如何實作。

若要視覺化結構描述的外觀，讓我們檢閱簡單 GraphQL 結構描述的內容。在生產程式碼中，您的結構描述通常位於名為 `schema.graphql`或 的檔案中`schema.json`。假設我們正在開發實作 GraphQL 服務的專案。此專案會儲存公司人員資料，而 `schema.graphql` 檔案會用來擷取人員資料，並將新人員新增至資料庫。程式碼可能如下所示：

------
#### [ schema.graphql ]

```
type Person {                                  
   id: ID!
   name: String                                  
   age: Int
}
type Query {                                   
  people: [Person]
}
type Mutation {
  addPerson(id: ID!, name: String, age: Int): Person
}
```

------

我們可以看到結構描述中定義了三種類型：`Person`、 `Query`和 `Mutation`。查看 `Person`，我們可以猜測這是公司員工執行個體的藍圖，這會讓此類型成為物件。在其範圍內，我們看到 `id`、 `name`和 `age`。這些是定義 之屬性的欄位`Person`。這表示我們的資料來源會將每個 `Person`的 `String` 儲存`name`為純量 （基本） 類型`age`和純量 `Int` （基本） 類型。`id` 可做為每個 的特殊唯一識別符`Person`。它也是以 `!`符號表示的必要值。

接下來的兩個物件類型行為不同。GraphQL 會為特殊物件類型保留一些關鍵字，以定義資料在結構描述中填入的方式。`Query` 類型會從來源擷取資料。在我們的範例中，我們的查詢可能會從資料庫擷取`Person`物件。這可能會提醒您 RESTful 術語中的`GET`操作。`Mutation` 將修改資料。在我們的範例中，我們的變動可能會將更多`Person`物件新增至資料庫。這可能會提醒您變更狀態的操作，例如 `PUT`或 `POST`。本節稍後將說明所有特殊物件類型的行為。

假設範例中`Query`的 會從資料庫擷取物件。如果我們查看 的欄位`Query`，就會看到一個名為 的欄位`people`。其欄位值為 `[Person]`。這表示我們希望擷取`Person`資料庫中的一些 執行個體。不過，新增括號表示我們想要傳回所有`Person`執行個體的清單，而不只是特定執行個體。

`Mutation` 類型負責執行變更狀態的操作，例如資料修改。變動負責對資料來源執行一些變更狀態的操作。在我們的範例中，我們的變動包含名為 的操作`addPerson`，將新`Person`物件新增至資料庫。變動會使用 `Person`，並預期輸入 `id`、 `name`和 `age` 欄位。

此時，您可能會想知道 操作的運作方式，`addPerson`如果沒有程式碼實作，因為它應該會執行一些行為，看起來很像具有函數名稱和參數的函數。目前，它無法運作，因為結構描述僅做為宣告。若要實作 的行為`addPerson`，我們必須新增解析程式。解析程式是程式碼的單位，每當呼叫其相關聯的欄位 （在此案例中為 `addPerson`操作） 時就會執行。如果您想要使用 操作，您必須在某個時間點新增解析程式實作。透過某種方式，您可以將結構描述操作視為函數宣告，並將解析程式視為定義。解析程式將在不同的章節中說明。

此範例僅顯示結構描述操作資料的最簡單方式。您可以利用 GraphQL 和 的功能來建置複雜、強大且可擴展的應用程式 AWS AppSync。在下一節中，我們將定義您可以在結構描述中使用的所有不同類型和欄位行為。

# GraphQL 類型
<a name="graphql-types"></a>

GraphQL 支援許多不同的類型。如上一節所示，類型會定義資料的形狀或行為。它們是 GraphQL 結構描述的基本建置區塊。

類型可以分類為輸入和輸出。輸入是允許做為特殊物件類型 (`Query`、 等） 的引數傳入的類型`Mutation`，而輸出類型會嚴格用於存放和傳回資料。類型及其分類的清單如下所示：
+ **物件**：物件包含描述實體的欄位。例如，物件可以是類似 的物件，`book`其中包含描述其特性的欄位`publishingYear`，例如 `authorName`、 等。它們是嚴格輸出類型。
+ **純量**：這些是基本類型，例如 int、string 等。它們通常會指派給欄位。使用 `authorName` 欄位做為範例，可以指派`String`純量來存放名稱，例如 "John Smith"。純量可以是輸入和輸出類型。
+ **輸入**：輸入可讓您將一組欄位做為引數傳遞。它們的結構與物件非常類似，但可以做為引數傳遞給特殊物件。輸入可讓您定義其範圍內的純量、列舉和其他輸入。輸入只能是輸入類型。
+ **特殊物件**：特殊物件會執行變更狀態的操作，並執行大量繁重的服務。有三種特殊物件類型：查詢、變動和訂閱。查詢通常會擷取資料；變動操作資料；訂閱會開啟和維護用戶端和伺服器之間的雙向連線，以進行持續通訊。特殊物件的功能不是輸入或輸出。
+ **列舉**：列舉是預先定義的法律值清單。如果您呼叫列舉，其值只能是其範圍中定義的值。例如，如果您有一個名為 的列舉，`trafficLights`描述流量訊號清單，它可以具有 `redLight`和 等值，`greenLight`但不能有 等值`purpleLight`。真正的交通燈只會有這麼多訊號，因此您可以使用列舉來定義它們，並在參考 時強制它們成為唯一的法律值`trafficLight`。列舉可以是輸入和輸出類型。
+ **聯集/介面**：聯集可讓您根據用戶端請求的資料，在請求中傳回一或多個物件。例如，如果您的`Book`類型具有 `title` 欄位，`Author`而類型具有 `name` 欄位，則可以在這兩種類型之間建立聯集。如果您的用戶端想要查詢資料庫以取得片語「Julius Caesar」，則聯集可以從 傳回 *Julius Caesar* (William Shakespeare 的播放），`Book``title`並從 傳回 *Julius Caesar* `Author` ( *Commentarii de Bello Gallico* 的作者）`name`。聯集只能是輸出類型。

  介面是 物件必須實作的一組欄位。這與 Java 等程式設計語言的界面略有相似，您必須在其中實作界面中定義的欄位。例如，假設您建立了名為 的界面`Book`，其中包含 `title` 欄位。假設您稍後建立了名為 的類型`Novel`，該類型已實作 `Book`。您的 `Novel`必須包含 `title` 欄位。不過，您的 `Novel` 也可以包含不在 介面中的其他欄位，例如 `pageCount`或 `ISBN`。介面只能是輸出類型。

以下各節將說明每種類型如何在 GraphQL 中運作。

## 物件
<a name="object-components"></a>

GraphQL 物件是您將在生產程式碼中看到的主要類型。在 GraphQL 中，您可以將物件視為不同欄位的群組 （類似於其他語言的變數），每個欄位都由可保留值的類型 （通常是純量或其他物件） 定義。物件代表可從您的服務實作擷取/控制的資料單位。

使用 `Type`關鍵字宣告物件類型。讓我們稍微修改結構描述範例：

```
type Person {
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}
```

此處的物件類型為 `Person`和 `Occupation`。每個物件都有自己的欄位和自己的類型。GraphQL 的一項功能是能夠將欄位設定為其他類型。您可以在 中看到 `occupation` 欄位`Person`包含 `Occupation` 物件類型。我們可以建立此關聯，因為 GraphQL 只描述資料，而不是服務的實作。

## 純量
<a name="scalar-components"></a>

純量基本上是保留值的基本類型。在 中 AWS AppSync，純量有兩種類型：預設 GraphQL 純量和 AWS AppSync 純量。純量通常用於在物件類型中存放欄位值。預設 GraphQL 類型包括 `Int`、`Float`、`Boolean`、 `String`和 `ID`。讓我們再次使用上一個範例：

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}
```

轉出 `name`和 `title` 欄位，兩者都保留純量。 `String` `Name`可能會傳回字串值，例如 "`John Smith`"，而標題可能會傳回類似 "`firefighter`" 的值。有些 GraphQL 實作也支援使用 `Scalar`關鍵字的自訂純量，並實作類型的行為。不過， AWS AppSync 目前**不支援**自訂純量。如需純量清單，請參閱 [中的純量類型 AWS AppSync](https://docs.aws.amazon.com//appsync/latest/devguide/scalars.html)。

## 輸入
<a name="input-components"></a>

由於輸入和輸出類型的概念，傳入引數時會有一些限制。通常需要傳入的類型會受到限制，特別是物件。您可以使用輸入類型來略過此規則。輸入是包含純量、列舉和其他輸入類型的類型。

輸入是使用`input`關鍵字定義：

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input personInput { 
  id: ID!
  name: String
  age: Int
  occupation: occupationInput
}

input occupationInput {
  title: String
}
```

如您所見，我們可以有模擬原始類型的個別輸入。這些輸入通常會用在您的欄位操作中，如下所示：

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input occupationInput {
  title: String
}

type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

請注意，我們仍以 `occupationInput` 代替 `Occupation`來建立 `Person`。

這只是輸入的一個案例。它們不一定需要 1：1 複製物件，而且在生產程式碼中，您很可能不會像這樣使用物件。利用 GraphQL 結構描述，最好只定義您需要輸入的內容做為引數。

此外，相同的輸入可用於多個操作，但我們不建議這樣做。每個操作理想情況下都應包含自己的唯一輸入複本，以防結構描述的需求變更。

## 特殊物件
<a name="special-object-components"></a>

GraphQL 會為特殊物件保留一些關鍵字，以定義結構描述如何擷取/處理資料的一些商業邏輯。結構描述中最多可以有其中一個關鍵字。它們可做為用戶端針對 GraphQL 服務執行之所有請求資料的進入點。

也會使用 `type`關鍵字定義特殊物件。雖然它們的使用方式與一般物件類型不同，但其實作非常類似。

------
#### [ Queries ]

查詢與 中的`GET`操作非常類似，因為它們執行唯讀擷取以從您的來源取得資料。在 GraphQL 中， `Query`會定義針對伺服器提出請求之用戶端的所有進入點。`Query` 您的 GraphQL 實作中一律會有 。

以下是我們在先前結構描述範例中使用的 `Query`和 修改過的物件類型：

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}
type Occupation {
  title: String
}
type Query {                                   
  people: [Person]
}
```

我們的 `Query`包含一個名為 的欄位`people`，從資料來源傳回`Person`執行個體清單。假設我們需要變更應用程式的行為，現在我們只需要針對個別用途傳回`Occupation`執行個體的清單。我們可以直接將其新增至查詢：

```
type Query {                                   
  people: [Person]
  occupations: [Occupation]
}
```

在 GraphQL 中，我們可以將查詢視為請求的單一來源。如您所見，這可能會比 RESTful 實作更簡單，這些實作可能會使用不同的端點來達成相同的物件 (`.../api/1/people` 和 `.../api/1/occupations`)。

假設我們有此查詢的解析程式實作，我們現在可以執行實際的查詢。當 `Query`類型存在時，我們必須明確呼叫它，才能在應用程式的程式碼中執行。您可以使用 `query`關鍵字來完成此操作：

```
query getItems {
   people {
      name
   }
   occupations {
      title
   }
}
```

如您所見，此查詢稱為 `getItems`並傳回 `people`(`Person`物件清單） 和 `occupations`(`Occupation`物件清單）。在 中`people`，我們只會傳回每個 `name`的欄位`Person`，同時傳回每個 `title`的欄位`Occupation`。回應可能如下所示：

```
{
  "data": {
    "people": [
      {
        "name": "John Smith"
      },
      {
        "name": "Andrew Miller"
      },
      .
      .
      .
    ],
    "occupations": [
      {
        "title": "Firefighter"
      },
      {
        "title": "Bookkeeper"
      },
      .
      .
      .
    ]
  }
}
```

範例回應顯示資料如何遵循查詢的形狀。擷取的每個項目都會列在 欄位的範圍內。 `people`和 `occupations`會以個別的清單傳回物件。雖然有用，但修改查詢以傳回人員名稱和職業清單可能更為方便：

```
query getItems {
   people {
      name   
      occupation {
        title
      }
}
```

這是合法修改，因為我們的`Person`類型包含 類型的`occupation`欄位`Occupation`。在 範圍內列出時`people`，我們會傳回每個 `Person`的 ，`name`以及其`Occupation`與 相關聯的 `title`。回應可能如下所示：

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",
        "occupation": {
          "title": "Firefighter"
        }
      },
      {
        "name": "Andrew Miller",
        "occupation": {
          "title": "Bookkeeper"
        }
      },
      .
      .
      .
    ]
  }
}
```

------
#### [ Mutations ]

變動類似於狀態變更的操作，例如 `PUT`或 `POST`。他們會執行寫入操作來修改來源中的資料，然後擷取回應。它們會定義資料修改請求的進入點。與查詢不同，根據專案的需求，變動可能會也可能不會包含在結構描述中。以下是結構描述範例中的變動：

```
type Mutation {
  addPerson(id: ID!, name: String, age: Int): Person
}
```

`addPerson` 欄位代表一個`Person`將 新增至資料來源的進入點。 `addPerson`是欄位名稱；`id`、 `name`和 `age`是參數； `Person`是傳回類型。回顧 `Person`類型：

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}
```

我們已新增 `occupation` 欄位。不過，我們無法將此欄位`Occupation`直接設定為 ，因為物件無法做為引數傳入；它們是嚴格輸出類型。我們應該改為傳遞具有與 引數相同欄位的輸入：

```
input occupationInput {
  title: String
}
```

 我們也可以在建立新`Person`執行個體時，輕鬆更新我們的 `addPerson` 以包含此參數：

```
type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

以下是更新的結構描述：

```
type Person { 
  id: ID!
  name: String
  age: Int
  occupation: Occupation
}

type Occupation {
  title: String
}

input occupationInput {
  title: String
}

type Mutation {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput): Person
}
```

請注意， `occupation`將從 傳入 `title` 欄位`occupationInput`，以完成 的建立，`Person`而不是原始`Occupation`物件。假設我們有 的解析程式實作`addPerson`，現在可以執行實際的變動。當 `Mutation`類型存在時，我們必須明確呼叫它，才能在應用程式的程式碼中執行。您可以使用 `mutation`關鍵字來完成此操作：

```
mutation createPerson {
  addPerson(id: ID!, name: String, age: Int, occupation: occupationInput) {
    name
    age
    occupation {
      title
    }
  }
}
```

此變動稱為 `createPerson`，而 `addPerson`是 操作。若要建立新的 `Person`，我們可以輸入 `id`、`age`、 `name`和 的引數`occupation`。在 範圍內`addPerson`，我們也可以看到其他欄位`age`，例如 `name`、 等。這是您的回應；這些是`addPerson`操作完成後將傳回的欄位。以下是範例的最後部分：

```
mutation createPerson {
  addPerson(id: "1", name: "Steve Powers", age: "50", occupation: "Miner") {
    id
    name
    age
    occupation {
      title
    }
  }
}
```

使用此變動，結果可能如下所示：

```
{
  "data": {
    "addPerson": {
      "id": "1",
      "name": "Steve Powers",
      "age": "50",
      "occupation": {
        "title": "Miner"
      }
    }
  }
}
```

如您所見，回應會以我們變動中定義的相同格式傳回我們請求的值。最佳實務是傳回所有修改過的值，以減少混淆，以及未來需要更多查詢。變動可讓您在其範圍內包含多個操作。它們將依變動中列出的順序依序執行。例如，如果我們建立另一個名為 的操作`addOccupation`，將任務標題新增至資料來源，我們可以在 之後的變動中呼叫此 `addPerson`。 `addPerson`會先處理，再處理 `addOccupation`。

------
#### [ Subscriptions ]

訂閱使用 [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_client_applications) 在伺服器及其用戶端之間開啟持久的雙向連線。一般而言，用戶端會訂閱或接聽伺服器。只要伺服器進行伺服器端變更或執行事件，訂閱的用戶端就會收到更新。當訂閱多個用戶端，且需要通知伺服器或其他用戶端發生變更時，此類型的通訊協定非常有用。例如，訂閱可用來更新社交媒體摘要。使用者 A 和使用者 B 可能有兩個使用者，每當他們收到直接訊息時，都會訂閱自動通知更新。用戶端 A 上的使用者 A 可以傳送直接訊息給用戶端 B 上的使用者 B。使用者 A 的用戶端會傳送直接訊息，由伺服器處理。然後，伺服器會在傳送自動通知至用戶端 B 時，將直接訊息傳送至使用者 B 的帳戶。

以下是`Subscription`我們可以新增至結構描述範例的 範例：

```
type Subscription {                                   
  personAdded: Person
}
```

只要將新的 `Person` 新增至資料來源， `personAdded` 欄位就會傳送訊息給訂閱的用戶端。假設我們有 的解析程式實作`personAdded`，現在可以使用訂閱。當 `Subscription`類型存在時，我們必須明確呼叫它，才能在應用程式的程式碼中執行。您可以使用 `subscription`關鍵字來完成此操作：

```
subscription personAddedOperation {
  personAdded {
    id
    name
  }
}
```

訂閱稱為 `personAddedOperation`，操作為 `personAdded`。 `personAdded`會傳回新`Person`執行個體的 `id`和 `name` 欄位。查看變動範例，我們使用`Person`此操作新增 ：

```
addPerson(id: "1", name: "Steve Powers", age: "50", occupation: "Miner")
```

如果用戶端已訂閱新新增 的更新`Person`，則在`addPerson`執行後可能會看到：

```
{
  "data": {
    "personAdded": {
      "id": "1",
      "name": "Steve Powers"
    }
  }
}
```

以下是訂閱提供的摘要：

訂閱是雙向通道，可讓用戶端和伺服器接收快速但穩定的更新。他們通常會使用 WebSocket 通訊協定，這會建立標準化且安全的連線。

訂閱可靈活運作，減少連線設定開銷。一旦訂閱，用戶端就可以在訂閱上長時間繼續執行。他們通常會允許開發人員量身打造訂閱的生命週期，並設定將請求哪些資訊，藉此有效率地使用運算資源。

一般而言，訂閱可讓用戶端一次進行多個訂閱。由於與 相關 AWS AppSync，訂閱僅用於從 AWS AppSync 服務接收即時更新。它們無法用於執行查詢或變動。

訂閱的主要替代方案是輪詢，它會以設定的間隔傳送查詢以請求資料。此程序通常比訂閱效率低，並對用戶端和後端造成很大壓力。

------

我們的結構描述範例中未提及的一件事，就是您的特殊物件類型也必須在`schema`根中定義。因此，當您在 中匯出結構描述時 AWS AppSync，可能如下所示：

------
#### [ schema.graphql ]

```
schema {
  query: Query
  mutation: Mutation
  subscription: Subscription
}

.
.
.

type Query {                                   
  # code goes here
}
type Mutation {                                   
  # code goes here
}
type Subscription {                                   
  # code goes here
}
```

------

## 列舉
<a name="enum-components"></a>

列舉或列舉是限制類型或欄位可能具有之法律引數的特殊純量。這表示每當列舉在結構描述中定義時，其關聯的類型或欄位將僅限於列舉中的值。列舉會序列化為字串純量。請注意，不同的程式設計語言可能會以不同的方式處理 GraphQL 列舉。例如，JavaScript 不支援原生列舉，因此列舉值可以改為映射至整數值。

列舉是使用 `enum`關鍵字來定義。範例如下：

```
enum trafficSignals {
  solidRed
  solidYellow
  solidGreen
  greenArrowLeft
  ...
}
```

呼叫`trafficLights`列舉時，引數只能是 `solidRed`、`solidYellow`、 `solidGreen`（等）。使用列舉來描述具有不同但有限選擇數量的物件是很常見的。

## 聯集/界面
<a name="union-interface-components"></a>

請參閱 [GraphQL 中的界面和聯集](https://docs.aws.amazon.com/appsync/latest/devguide/interfaces-and-unions.html)。 GraphQL

# GraphQL 欄位
<a name="graphql-fields"></a>

欄位存在於 類型的範圍內，並保留從 GraphQL 服務請求的值。這些與其他程式設計語言的變數非常相似。例如，以下是`Person`物件類型：

```
type Person {                                  
   name: String                                  
   age: Int
}
```

在此情況下，欄位分別為 `name`和 `age` 並保留 `String`和 `Int`值。像上述所示的物件欄位可以用作查詢和變動之欄位 （操作） 中的輸入。例如，請參閱`Query`下列內容：

```
type Query {                                   
  people: [Person]
}
```

`people` 欄位正在`Person`從資料來源請求 的所有執行個體。當您在 GraphQL 伺服器`Person`中新增或擷取 時，您可以預期資料會遵循您類型和欄位的格式，也就是說，結構描述中資料的結構會決定如何在回應中建構資料：

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",
        "age": "50"
      },
      {
        "name": "Andrew Miller",
        "age": "60"
      },
      .
      .
      .
    ]
  }
}
```

欄位在建構資料中扮演重要角色。下面說明了幾個額外的屬性，可以套用到欄位以進行更多自訂。

## 清單
<a name="list-components"></a>

清單會傳回指定類型的所有項目。您可以使用括號 將清單新增至欄位的類型`[]`：

```
type Person { 
  name: String
  age: Int
}
type Query {                                   
  people: [Person]
}
```

在 中`Query`，週圍括號`Person`表示您想要`Person`從資料來源傳回 的所有執行個體做為陣列。在回應中，每個 的 `name`和 `age`值`Person`會以單一的分隔清單傳回：

```
}
  "data": {
    "people": [
      {
        "name": "John Smith",         # Data of Person 1
        "age": "50"
      },
      {
        "name": "Andrew Miller",      # Data of Person 2
        "age": "60"
      },
      .                               # Data of Person N
      .
      .
    ]
  }
}
```

您不限於特殊物件類型。您也可以在一般物件類型的欄位中使用清單。

## 非 Null
<a name="non-null-components"></a>

非 Null 表示回應中不可為 Null 的欄位。您可以使用 `!`符號將欄位設定為非空值：

```
type Person { 
  name: String!
  age: Int
}
type Query {                                   
  people: [Person]
}
```

`name` 欄位不能明確為 null。如果您要查詢資料來源，並為此欄位提供 null 輸入，則會擲回錯誤。

您可以結合清單和非 Null。比較這些查詢：

```
type Query {                                   
  people: [Person!]      # Use case 1
}

.
.
.

type Query {                                   
  people: [Person]!      # Use case 2
}

.
.
.

type Query {                                   
  people: [Person!]!     # Use case 3
}
```

在使用案例 1 中，清單不能包含 null 項目。在使用案例 2 中，清單本身無法設定為 null。在使用案例 3 中，清單及其項目不能為 null。不過，無論如何，您仍然可以傳回空白清單。

如您所見，GraphQL 中有許多移動元件。在本節中，我們展示了簡單結構描述的結構，以及結構描述支援的不同類型和欄位。在下一節中，您將探索 GraphQL API 的其他元件，以及它們如何使用結構描述。