

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

# GraphQL 類型參考
<a name="type-reference"></a>

GraphQL 中的純量類型代表 GraphQL 結構描述中的基本分葉值。這些是解析為單一值的最基本資料類型。與物件類型不同，純量類型不能有子欄位。GraphQL 隨附一組預設純量類型：
+ **Int**：帶正負號的 32 位元整數 
+ **浮點數**：帶正負號的雙精度浮點值 
+ **字串**：UTF-8 字元序列 
+ **布林值**：true 或 false 值
+ **ID**：唯一識別符，通常用於重新擷取物件或作為快取的金鑰

這些純量類型可做為結構描述中更複雜類型的建置區塊。它們用於定義包含簡單、單一值的欄位。除了這些內建純量之外， 還為不同的使用案例 AWS AppSync 提供額外的純量。

GraphQL 中的界面和聯集是抽象類型，允許彈性和可擴展的結構描述設計。它們提供將相關類型分組並啟用多態查詢的機制。GraphQL 中的界面是一種抽象類型，可定義類型必須包含的一組欄位，以實作界面。它透過指定實作類型必須擁有的一組常用欄位，做為物件的合約。當您想要傳回可有多種不同類型的物件或欄位，但仍有一些保證欄位時，界面非常有用。相較之下，GraphQL 中的 Union 代表的類型可以是多種物件類型之一，但不會在這些類型之間定義任何常用欄位。當您需要傳回可具有多種類型的欄位時，聯集會很有幫助，而且這些類型不一定共用共同的欄位。界面和聯集在欄位可能傳回不同資料類型的情況下特別有用，可讓用戶端根據傳回的類型查詢特定欄位。

本節用作結構描述類型的參考。

**主題**
+ [GraphQL 中的純量類型](https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html)
+ [GraphQL 中的界面和聯集](https://docs.aws.amazon.com/appsync/latest/devguide/interfaces-and-unions.html)

# GraphQL 中的純量類型
<a name="scalars"></a>

GraphQL 物件類型具有名稱和欄位，而且這些欄位可以具有子欄位。最終，物件類型的欄位必須解析為*純量*類型，代表查詢的葉子。如需物件類型和純量的詳細資訊，請參閱 GraphQL 網站上的[結構描述和類型](https://graphql.org/learn/schema/)。

除了預設的一組 GraphQL 純量之外， AWS AppSync 也可讓您使用以 *AWS*字首開頭**的服務定義**純量。 AWS AppSync 不支援建立**使用者定義** （自訂） 純量。您必須使用預設 *AWS* 或純量。

您無法使用 *AWS*做為自訂物件類型的字首。

下節是結構描述類型參考。

## 預設純量
<a name="graph-ql-base-scalars"></a>

GraphQL 定義下列預設純量：

### 預設純量清單
<a name="graph-ql-base-scalars-list"></a>

`ID`  
物件的唯一識別符。此純量會序列化為 ，`String`但並非供人閱讀。

`String`  
UTF-8 字元序列。

`Int`  
介於 -(231) 和 231-1 之間的整數值。

`Float`  
IEEE 754 浮點值。

`Boolean`  
布林值，`true` 或 `false`。

## AWS AppSync 純量
<a name="graph-ql-aws-appsync-scalars"></a>

AWS AppSync 定義下列純量：

### AWS AppSync 純量清單
<a name="graph-ql-aws-appsync-scalars-list"></a>

`AWSDate`  
格式為 的擴充 [ISO 8601 日期](https://en.wikipedia.org/wiki/ISO_8601#Calendar_dates)字串`YYYY-MM-DD`。

`AWSTime`  
格式為 的擴充 [ISO 8601 時間](https://en.wikipedia.org/wiki/ISO_8601#Times)字串`hh:mm:ss.sss`。

`AWSDateTime`  
擴充 [ISO 8601 日期和時間](https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations)字串，格式為 `YYYY-MM-DDThh:mm:ss.sssZ`。

**注意**  
`AWSDate`、 `AWSTime`和 `AWSDateTime` 純量可以選擇性地包含[時區位移](https://en.wikipedia.org/wiki/ISO_8601#Time_zone_designators)。例如，值 `1970-01-01Z`、 `1970-01-01-07:00`和 `1970-01-01+05:30` 都對 有效`AWSDate`。時區位移必須是 `Z`(UTC) 或以小時和分鐘為單位的位移 （以及選擇性的秒數）。例如：`±hh:mm:ss`。時區位移中的秒欄位被視為有效，即使它不是 ISO 8601 標準的一部分。

`AWSTimestamp`  
整數值，代表 前後的秒數`1970-01-01-T00:00Z`。

`AWSEmail`  
採用 [RFC 822 ](https://tools.ietf.org/html/rfc822)`local-part@domain-part`所定義格式的電子郵件地址。

`AWSJSON`  
JSON 字串。任何有效的 JSON 建構模組都會自動剖析並載入解析程式程式碼，做為映射、清單或純量值，而非常值輸入字串。未引用的字串或其他無效的 JSON 會導致 GraphQL 驗證錯誤。

`AWSPhone`  
電話號碼。此值會儲存為字串。電話號碼可以包含空格或連字號，以分隔數字群組。沒有國家/地區代碼的電話號碼假設為遵守[北美編號計劃 (NANP)](https://en.wikipedia.org/wiki/North_American_Numbering_Plan) 的美國/北美電話號碼。

`AWSURL`  
[RFC 1738 ](https://tools.ietf.org/html/rfc1738)定義的 URL。例如 `https://www.amazon.com/dp/B000NZW3KC/` 或 `mailto:example@example.com`。URLs 必須包含結構描述 (`http`、`mailto`)，且路徑部分中不能包含兩個正斜線 (`//`)。

`AWSIPAddress`  
有效的 IPv4 或 IPv6 地址。IPv4 地址預期為四點符號 (`123.12.34.56`)。IPv6 地址預期為非括號、冒號分隔格式 (`1a2b:3c4b::1234:4567`)。您可以包含選用的 CIDR 尾碼 (`123.45.67.89/16`) 來表示子網路遮罩。

## 結構描述用量範例
<a name="example-schema-usage"></a>

下列範例 GraphQL 結構描述使用所有自訂純量做為「物件」，並顯示基本 put、get 和 list 操作的解析程式請求和回應範本。最後，此範例示範如何在執行查詢和變動時使用此功能。

```
type Mutation {
    putObject(
        email: AWSEmail,
        json: AWSJSON,
        date: AWSDate,
        time: AWSTime,
        datetime: AWSDateTime,
        timestamp: AWSTimestamp,
        url: AWSURL,
        phoneno: AWSPhone,
        ip: AWSIPAddress
    ): Object
}

type Object {
    id: ID!
    email: AWSEmail
    json: AWSJSON
    date: AWSDate
    time: AWSTime
    datetime: AWSDateTime
    timestamp: AWSTimestamp
    url: AWSURL
    phoneno: AWSPhone
    ip: AWSIPAddress
}

type Query {
    getObject(id: ID!): Object
    listObjects: [Object]
}

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

以下是 的請求範本`putObject`可能看起來的樣子。`putObject` 使用 `PutItem`操作來建立或更新 Amazon DynamoDB 資料表中的項目。請注意，此程式碼片段沒有已設定的 Amazon DynamoDB 資料表做為資料來源。這只是用作範例：

```
{
    "version" : "2017-02-28",
    "operation" : "PutItem",
    "key" : {
        "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
    },
    "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
}
```

的回應範本會`putObject`傳回結果：

```
$util.toJson($ctx.result)
```

以下是 的請求範本`getObject`可能看起來的樣子。`getObject` 使用 `GetItem`操作來傳回指定主索引鍵之項目的一組屬性。請注意，此程式碼片段沒有已設定的 Amazon DynamoDB 資料表做為資料來源。這只是用作範例：

```
{
    "version": "2017-02-28",
    "operation": "GetItem",
    "key": {
        "id": $util.dynamodb.toDynamoDBJson($ctx.args.id),
    }
}
```

的回應範本會`getObject`傳回結果：

```
$util.toJson($ctx.result)
```

以下是 的請求範本`listObjects`可能看起來的樣子。`listObjects` 使用 `Scan`操作來傳回一或多個項目和屬性。請注意，此程式碼片段沒有已設定的 Amazon DynamoDB 資料表做為資料來源。這只是用作範例：

```
{
    "version" : "2017-02-28",
    "operation" : "Scan",
}
```

的回應範本會`listObjects`傳回結果：

```
$util.toJson($ctx.result.items)
```

以下是搭配 GraphQL 查詢使用此結構描述的一些範例：

```
mutation CreateObject {
    putObject(email: "example@example.com"
        json: "{\"a\":1, \"b\":3, \"string\": 234}"
        date: "1970-01-01Z"
        time: "12:00:34."
        datetime: "1930-01-01T16:00:00-07:00"
        timestamp: -123123
        url:"https://amazon.com"
        phoneno: "+1 555 764 4377"
        ip: "127.0.0.1/8"
    ) {
        id
        email
        json
        date
        time
        datetime
        url
        timestamp
        phoneno
        ip
    }
}

query getObject {
    getObject(id:"0d97daf0-48e6-4ffc-8d48-0537e8a843d2"){
        email
        url
        timestamp
        phoneno
        ip
    }
}

query listObjects {
    listObjects {
        json
        date
        time
        datetime
    }
}
```

# GraphQL 中的界面和聯集
<a name="interfaces-and-unions"></a>

GraphQL 類型系統支援[界面](https://graphql.org/learn/schema/#interfaces)。界面會公開特定的欄位組合，類型必須包含該組合以實作界面。

GraphQL 類型系統也支援 [Unions](https://graphql.org/learn/schema/#union-types)。聯集與界面相同，但它們不會定義一組常用的欄位。當可能的類型不共用邏輯階層時，使用者通常偏好使用聯集而非界面。

下節是結構描述類型參考。

## 介面範例
<a name="interfaces"></a>

我們可以代表代表任何類型的活動或人員集合的`Event`界面。有些可能的事件類型為 `Concert`、 `Conference`和 `Festival`。這些類型都具有常見的特性，包含名稱、事件進行的地點，以及開始和結束日期。這些類型也有差異； `Conference`提供發言者和研討會的清單，而 `Concert`具有執行頻帶。

在結構描述定義語言 (SDL) 中，`Event`界面的定義如下：

```
interface Event {
        id: ID!
        name : String!
        startsAt: String
        endsAt: String
        venue: Venue
        minAgeRestriction: Int
}
```

每個類型都會實作`Event`界面，如下所示：

```
type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}
```

界面可用來代表元素，而該元素可能有幾個類型。例如，我們可以搜尋在特定會場發生的所有事件。現在讓我們在結構描述上新增 `findEventsByVenue` 欄位，如下所示：

```
schema {
    query: Query
}

type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
}

type Venue {
    id: ID!
    name: String
    address: String
    maxOccupancy: Int
}

type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}

interface Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}
```

`findEventsByVenue` 會傳回 的清單`Event`。由於 GraphQL 界面欄位對於所有實作類型而言都是共通的，因此您可以在 `Event` 界面 (`id`、`name`、`startsAt`、`endsAt`、`venue` 和 `minAgeRestriction`) 選取任何欄位。此外，您可以使用 GraphQL [片段](https://graphql.org/learn/queries/#fragments)存取任何實作類型上的欄位，只是您必須指定該類型。

讓我們檢查使用 界面的 GraphQL 查詢範例。

```
query {
  findEventsAtVenue(venueId: "Madison Square Garden") {
    id
    name
    minAgeRestriction
    startsAt

    ... on Festival {
      performers
    }

    ... on Concert {
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

上述查詢會產生一個結果清單，伺服器預設會依據開始日期排序事件。

```
{
  "data": {
    "findEventsAtVenue": [
      {
        "id": "Festival-2",
        "name": "Festival 2",
        "minAgeRestriction": 21,
        "startsAt": "2018-10-05T14:48:00.000Z",
        "performers": [
          "The Singers",
          "The Screamers"
        ]
      },
      {
        "id": "Concert-3",
        "name": "Concert 3",
        "minAgeRestriction": 18,
        "startsAt": "2018-10-07T14:48:00.000Z",
        "performingBand": "The Jumpers"
      },
      {
        "id": "Conference-4",
        "name": "Conference 4",
        "minAgeRestriction": null,
        "startsAt": "2018-10-09T14:48:00.000Z",
        "speakers": [
          "The Storytellers"
        ],
        "workshops": [
          "Writing",
          "Reading"
        ]
      }
    ]
  }
}
```

由於結果會以單一事件集合的形式傳回，因此使用界面來表示常見特性非常有助於排序結果。

## 聯集範例
<a name="unions"></a>

如前所述，聯集不會定義常見的欄位集。搜尋結果可能代表許多不同的類型。使用 `Event` 結構描述，您可以定義 `SearchResult` 聯集，如下所示：

```
type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
    # Search across all content
    search(query: String!): [SearchResult]
}

union SearchResult = Conference | Festival | Concert | Venue
```

在此情況下，若要查詢聯`SearchResult`集上的任何欄位，您必須使用片段：

```
query {
  search(query: "Madison") {
    ... on Venue {
      id
      name
      address
    }

    ... on Festival {
      id
      name
      performers
    }

    ... on Concert {
      id
      name
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

## 類型解析 in AWS AppSync
<a name="type-resolution-in-appsynclong"></a>

類型解析是一種機制，GraphQL 引擎會透過這個機制將解析值識別為特定物件類型。

返回聯集搜尋範例，假設查詢產生結果，結果清單中的每個項目都必須顯示為`SearchResult`聯集定義的可能類型之一 （即 `Conference`、`Concert`、 `Festival`或 `Venue`)。

由於識別 `Festival`、`Venue` 或 `Conference` 的邏輯取決於應用程式要求，因此必須為 GraphQL 引擎提供提示，以便從原始結果中識別我們的類型。

With AWS AppSync，此提示由名為 的中繼欄位表示`__typename`，其值對應於識別的物件類型名稱。作為界面或聯集的傳回類型`__typename`需要 。

## 類型解析範例
<a name="type-resolution-example"></a>

讓我們重複使用之前的結構描述。您可以透過瀏覽到主控台並將以下項目新增至 **Schema (結構描述)** 頁面下來執行此動作：

```
schema {
    query: Query
}

type Query {
    # Retrieve Events at a specific Venue
    findEventsAtVenue(venueId: ID!): [Event]
    # Search across all content
    search(query: String!): [SearchResult]
}

union SearchResult = Conference | Festival | Concert | Venue

type Venue {
    id: ID!
    name: String!
    address: String
    maxOccupancy: Int
}

interface Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
}

type Festival implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performers: [String]
}

type Conference implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    speakers: [String]
    workshops: [String]
}

type Concert implements Event {
    id: ID!
    name: String!
    startsAt: String
    endsAt: String
    venue: Venue
    minAgeRestriction: Int
    performingBand: String
}
```

現在將解析程式附加到 `Query.search` 欄位。在 `Resolvers`區段中，選擇**連接**，建立新的 *NONE *類型的**資料來源**，然後命名為 *StubDataSource*。在此範例中，我們將假設從外部來源擷取結果，並將擷取結果硬式編碼至請求映射範本中。

在請求映射範本窗格中，輸入以下內容：

```
{
    "version" : "2018-05-29",
    "payload":
    ## We are effectively mocking our search results for this example
    [
        {
            "id": "Venue-1",
            "name": "Venue 1",
            "address": "2121 7th Ave, Seattle, WA 98121",
            "maxOccupancy": 1000
        },
        {
            "id": "Festival-2",
            "name": "Festival 2",
            "performers": ["The Singers", "The Screamers"]
        },
        {
            "id": "Concert-3",
            "name": "Concert 3",
            "performingBand": "The Jumpers"
        },
        {
            "id": "Conference-4",
            "name": "Conference 4",
            "speakers": ["The Storytellers"],
            "workshops": ["Writing", "Reading"]
        }
    ]
}
```

如果應用程式傳回類型名稱做為 `id` 欄位的一部分，則類型解析邏輯必須剖析 `id` 欄位以擷取類型名稱，然後將 `__typename` 欄位新增至每個結果。您可以在回應映射範本中執行該邏輯，如下所示：

**注意**  
如果您使用 Lambda 資料來源，也可以在 Lambda 函數中執行此任務。

```
#foreach ($result in $context.result)
    ## Extract type name from the id field.
    #set( $typeName = $result.id.split("-")[0] )
    #set( $ignore = $result.put("__typename", $typeName))
#end
$util.toJson($context.result)
```

執行下列查詢：

```
query {
  search(query: "Madison") {
    ... on Venue {
      id
      name
      address
    }

    ... on Festival {
        id
      name
      performers
    }

    ... on Concert {
      id
      name
      performingBand
    }

    ... on Conference {
      speakers
      workshops
    }
  }
}
```

此查詢會產生下列結果：

```
{
  "data": {
    "search": [
      {
        "id": "Venue-1",
        "name": "Venue 1",
        "address": "2121 7th Ave, Seattle, WA 98121"
      },
      {
        "id": "Festival-2",
        "name": "Festival 2",
        "performers": [
          "The Singers",
          "The Screamers"
        ]
      },
      {
        "id": "Concert-3",
        "name": "Concert 3",
        "performingBand": "The Jumpers"
      },
      {
        "speakers": [
          "The Storytellers"
        ],
        "workshops": [
          "Writing",
          "Reading"
        ]
      }
    ]
  }
}
```

類型解析邏輯會依據應用程式而有不同。例如，您可以有不同的識別邏輯，以檢查特定欄位或甚至結合欄位是否存在。也就是說，您可以偵測 `performers` 欄位是否存在以識別 `Festival`，或偵測 `speakers` 與 `workshops` 欄位的組合是否存在以識別 `Conference`。最終，由您決定要使用的邏輯。