

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

# 建構 GraphQL API （空白或匯入APIs)
<a name="blank-import-api"></a>

從空白範本建立 GraphQL API 之前，檢閱 GraphQL 的相關概念會有幫助。GraphQL API 有三個基本元件：

1. **結構描述**是包含資料形狀和定義的檔案。當用戶端向 GraphQL 服務提出請求時，傳回的資料將遵循結構描述的規格。如需詳細資訊，請參閱[GraphQL 結構描述](schema-components.md#aws-appsync-schema-components)。

1. **資料來源**會連接到您的結構描述。提出請求時，這是擷取和修改資料的位置。如需詳細資訊，請參閱[資料來源](data-source-components.md#aws-appsync-data-source-components)。

1. **解析程式**位於結構描述和資料來源之間。提出請求時，解析程式會對來源的資料執行 操作，然後傳回結果做為回應。如需詳細資訊，請參閱[解析程式](resolver-components.md#aws-appsync-resolver-components)。

![\[GraphQL API architecture showing schema, resolvers, and data sources connected via AppSync.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/appsync-architecture-graphql-api.png)


AWS AppSync 可讓您建立、編輯和存放結構描述和解析程式的程式碼，以管理您的 APIs。您的資料來源來自外部儲存庫，例如資料庫、DynamoDB 資料表和 Lambda 函數。如果您使用 AWS 服務來存放資料，或打算這麼做， 會在將資料從 AWS 您的帳戶與 GraphQL APIs 建立關聯時 AWS AppSync 提供近乎無縫的體驗。

在下一節中，您將了解如何使用 AWS AppSync 服務建立每個元件。

**Topics**
+ [設計 GraphQL 結構描述](designing-your-schema.md)
+ [連接資料來源](attaching-a-data-source.md)
+ [設定 AWS AppSync 解析程式](resolver-config-overview.md)
+ [搭配 CDK APIs](using-your-api.md)

# 設計 GraphQL 結構描述
<a name="designing-your-schema"></a>

GraphQL 結構描述是任何 GraphQL 伺服器實作的基礎。每個 GraphQL API 都由**單一**結構描述定義，其中包含描述請求資料如何填入的類型和欄位。流經 API 的資料和執行的操作必須針對結構描述進行驗證。

一般而言，[GraphQL 類型系統會](https://graphql.org/learn/schema/#type-system)描述 GraphQL 伺服器的功能，並用來判斷查詢是否有效。伺服器類型系統通常稱為該伺服器的結構描述，可包含不同的物件類型、純量類型、輸入類型等。GraphQL 是宣告式和強式類型，這表示類型將在執行時間妥善定義，並且只會傳回指定的類型。

AWS AppSync 可讓您定義和設定 GraphQL 結構描述。下一節說明如何使用 AWS AppSync的服務從頭開始建立 GraphQL 結構描述。

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

**提示**  
建議您先檢閱[結構描述](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)區段再繼續。

GraphQL 是實作 API 服務的強大工具。根據 [GraphQL 的網站](https://graphql.org/)，GraphQL 如下：

「*GraphQL 是 APIs的查詢語言，也是使用現有資料完成這些查詢的執行時間。GraphQL 提供 API 中資料的完整且易於理解的描述，讓用戶端能夠確切地詢問他們需要什麼，什麼都不做，讓隨著時間發展 APIs 變得更容易，並啟用強大的開發人員工具。*」

本節涵蓋 GraphQL 實作的第一部分：結構描述。使用上述引號，結構描述扮演「提供 API 中資料的完整且可理解描述」的角色。換句話說，GraphQL 結構描述是服務資料、操作及其之間關係的文字表示。結構描述會被視為 GraphQL 服務實作的主要進入點。令人意外的是，這通常是您在專案中做的第一件事之一。建議您先檢閱[結構描述](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)區段再繼續。

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

最簡單的結構描述將包含三種不同的資料類別：

1. **結構描述根**目錄：根目錄定義結構描述的進入點。它指向將對資料執行一些操作的欄位，例如新增、刪除或修改某個項目。

1. **類型**：這些是用來代表資料形狀的基本類型。您幾乎可以將這些視為物件或具有已定義特性之物件的抽象表示法。例如，您可以製作代表資料庫中人員的`Person`物件。每個人的特性都會`Person`在 中定義為 欄位。它們可以是人員的名稱、年齡、工作、地址等。

1. **特殊物件類型**：這些是定義結構描述中操作行為的類型。每個特殊物件類型每個結構描述定義一次。它們會先放置在結構描述根目錄，然後在結構描述內文中定義。特殊物件類型中的每個欄位都會定義您的解析程式要實作的單一操作。

假設您正在建立可存放作者和他們所撰寫書籍的服務，以將其納入考量。每個作者都有一個名稱和他們撰寫的書籍陣列。每本書都有一個名稱和相關聯的作者清單。我們也希望能夠新增或擷取書籍和作者。此關係的簡單 UML 表示方式可能如下所示：

![\[UML diagram showing Author and Book classes with attributes and methods, linked by association.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/GraphQL-UML-1.png)


在 GraphQL 中，實體`Author`和 `Book`代表結構描述中的兩種不同的物件類型：

```
type Author {
}

type Book {
}
```

`Author` 包含 `authorName`和 `Books`，而 `Book`包含 `bookName`和 `Authors`。這些可以表示為您類型範圍內的欄位：

```
type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}
```

如您所見，類型表示法非常接近圖表。不過，這些方法會變得較棘手。這些將放置在幾個特殊物件類型之一做為欄位。它們的特殊物件分類取決於其行為。GraphQL 包含三種基本的特殊物件類型：查詢、變動和訂閱。如需詳細資訊，請參閱[特殊物件](https://docs.aws.amazon.com//appsync/latest/devguide/graphql-types.html#special-object-components)。

由於 `getAuthor`和 `getBook` 都請求資料，因此它們將放置在`Query`特殊物件類型中：

```
type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}
```

操作會連結至查詢，而查詢本身會連結至結構描述。新增結構描述根將定義特殊物件類型 (`Query`在此案例中為 ) 做為其中一個進入點。這可以使用 `schema`關鍵字來完成：

```
schema {
  query: Query
}

type Author {
  authorName: String
  Books: [Book]
}

type Book {
  bookName: String
  Authors: [Author]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}
```

查看最後兩種方法，`addAuthor``addBook`並將資料新增至資料庫，因此它們將以`Mutation`特殊物件類型定義。不過，從[類型](https://docs.aws.amazon.com/appsync/latest/devguide/graphql-types.html#input-components)頁面，我們也知道不允許直接參考物件的輸入，因為它們是嚴格輸出類型。在這種情況下，我們無法使用 `Author`或 `Book`，因此我們需要使用相同的欄位建立輸入類型。在此範例中，我們新增了 `AuthorInput`和 `BookInput`，兩者都接受各自類型的相同欄位。然後，我們使用輸入做為參數來建立變動：

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

type Author {
  authorName: String
  Books: [Book]
}

input AuthorInput {
  authorName: String
  Books: [BookInput]
}

type Book {
  bookName: String
  Authors: [Author]
}

input BookInput {
  bookName: String
  Authors: [AuthorInput]
}

type Query {
  getAuthor(authorName: String): Author
  getBook(bookName: String): Book
}

type Mutation {
  addAuthor(input: [BookInput]): Author
  addBook(input: [AuthorInput]): Book
}
```

讓我們檢閱剛執行的操作：

1. 我們已使用 `Book`和 `Author`類型建立結構描述，以代表我們的實體。

1. 我們新增了包含實體特性的欄位。

1. 我們新增了查詢，以從資料庫擷取此資訊。

1. 我們新增了變動來操作資料庫中的資料。

1. 我們新增輸入類型來取代變動中的物件參數，以符合 GraphQL 的規則。

1. 我們已將查詢和變動新增至根結構描述，以便 GraphQL 實作了解根類型位置。

如您所見，建立結構描述的程序通常需要資料建模 （特別是資料庫建模） 的許多概念。您可以將結構描述視為符合來源資料的形狀。它也可以做為解析程式將實作的模型。在下列各節中，您將了解如何使用各種 AWS支援的工具和服務建立結構描述。

**注意**  
以下各節中的範例並非要在真正的應用程式中執行。它們只用來展示命令，因此您可以建置自己的應用程式。

## 建立結構描述
<a name="creating-schema"></a>

您的結構描述將位於名為 `schema.graphql`. AWS AppSync 的檔案中，允許使用者使用各種方法為其 GraphQL APIs 建立新的結構描述。在此範例中，我們將建立空白 API 以及空白結構描述。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在**儀表板**上，選擇 **Create API (建立 API)**。

   1. 在 **API 選項**下，選擇 **GraphQL APIs**、**從頭開始設計**，然後選擇**下一步**。

      1. 針對 **API 名稱**，請將預先填入的名稱變更為應用程式所需的名稱。

      1. 如需**聯絡詳細資訊**，您可以輸入聯絡點來識別 API 的管理員。此為選用欄位。

      1. 在**私有 API 組態**下，您可以啟用私有 API 功能。私有 API 只能從設定的 VPC 端點 (VPCE) 存取。如需詳細資訊，請參閱[私有 APIs](https://docs.aws.amazon.com/appsync/latest/devguide/using-private-apis.html)。

         不建議在此範例中啟用此功能。檢閱您的輸入後，請選擇**下一步**。

   1. 在**建立 GraphQL 類型**下，您可以選擇建立 DynamoDB 資料表以用作資料來源，或略過此項目並在稍後執行。

      在此範例中，選擇**稍後建立 GraphQL 資源**。我們將在單獨的區段中建立資源。

   1. 檢閱您的輸入，然後選擇**建立 API**。

1. 您將位於特定 API 的儀表板中。您可以指出 ，因為 API 的名稱會位於儀表板頂端。如果不是這種情況，您可以在 **Sidebar** 中選取 **APIs**，然後在 API **儀表板中選擇您的 APIs**。

   1. 在 API 名稱下方的 **Sidebar** 中，選擇**結構描述**。

1. 在**結構描述編輯器**中，您可以設定 `schema.graphql` 檔案。它可以是空的或填滿從模型產生的類型。在右側，您有**將解析程式**連接至結構描述欄位的解析程式區段。我們不會查看本節中的解析程式。

------
#### [ CLI ]

**注意**  
使用 CLI 時，請確定您擁有在 服務中存取和建立資源的正確許可。您可能想要為需要存取服務的非管理員使用者設定[最低權限](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege)政策。如需 AWS AppSync 政策的詳細資訊，請參閱 [的 Identity and Access Management AWS AppSync](https://docs.aws.amazon.com//appsync/latest/devguide/security-iam.html)。  
此外，如果您尚未閱讀主控台版本，建議您先閱讀。

1. 如果您尚未這麼做，請 AWS [安裝](https://docs.aws.amazon.com//cli/latest/userguide/cli-chap-getting-started.html) CLI，然後新增您的[組態](https://docs.aws.amazon.com//cli/latest/userguide/cli-configure-quickstart.html)。

1. 執行 [https://docs.aws.amazon.com/cli/latest/reference/appsync/create-graphql-api.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-graphql-api.html)命令來建立 GraphQL API 物件。

   您需要為此特定命令輸入兩個參數：

   1. 您 API `name`的 。

   1. `authentication-type`，或用於存取 API 的登入資料類型 (IAM、OIDC 等）。
**注意**  
必須設定其他參數，例如 `Region` ，但通常會預設為您的 CLI 組態值。

   範例命令可能如下所示：

   ```
   aws appsync create-graphql-api --name testAPI123 --authentication-type API_KEY
   ```

   輸出會在 CLI 中傳回。範例如下：

   ```
   {
       "graphqlApi": {
           "xrayEnabled": false,
           "name": "testAPI123",
           "authenticationType": "API_KEY",
           "tags": {},
           "apiId": "abcdefghijklmnopqrstuvwxyz",
           "uris": {
               "GRAPHQL": "https://zyxwvutsrqponmlkjihgfedcba.appsync-api.us-west-2.amazonaws.com/graphql",
               "REALTIME": "wss://zyxwvutsrqponmlkjihgfedcba.appsync-realtime-api.us-west-2.amazonaws.com/graphql"
           },
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz"
       }
   }
   ```

1. 
**注意**  
這是選用的命令，採用現有的結構描述，並使用 base-64 Blob 將其上傳至 AWS AppSync 服務。基於此範例，我們不會使用此命令。

   執行 [https://docs.aws.amazon.com/cli/latest/reference/appsync/start-schema-creation.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/start-schema-creation.html) 命令。

   您需要為此特定命令輸入兩個參數：

   1. 上一個步驟`api-id`的 。

   1. 結構描述`definition`是 base-64 編碼的二進位 Blob。

   範例命令可能如下所示：

   ```
    aws appsync start-schema-creation --api-id abcdefghijklmnopqrstuvwxyz --definition "aa1111aa-123b-2bb2-c321-12hgg76cc33v"
   ```

   將傳回輸出：

   ```
   {
       "status": "PROCESSING"
   }
   ```

   此命令不會在處理後傳回最終輸出。您必須使用單獨的命令 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/get-schema-creation-status.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/get-schema-creation-status.html)來查看結果。請注意，這兩個命令是非同步的，因此即使結構描述仍在建立中，您也可以檢查輸出狀態。

------
#### [ CDK ]

**提示**  
在使用 CDK 之前，建議您檢閱 CDK 的[官方文件](https://docs.aws.amazon.com/cdk/v2/guide/home.html)以及 CDK AWS AppSync參考。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
下列步驟只會顯示用來新增特定資源之程式碼片段的一般範例。這**並非**您生產程式碼中的工作解決方案。我們也假設您已經有運作中的應用程式。

1. CDK 的起點略有不同。理想情況下，應該已建立您的`schema.graphql`檔案。您只需要使用副檔名建立新的`.graphql`檔案。這可以是空白檔案。

1. 一般而言，您可能需要將匯入指令新增至您正在使用的服務。例如，它可能會遵循以下表單：

   ```
   import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
   import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
   ```

   若要新增 GraphQL API，您的堆疊檔案需要匯入 AWS AppSync 服務：

   ```
   import * as appsync from 'aws-cdk-lib/aws-appsync';
   ```
**注意**  
這表示我們正在`appsync`關鍵字下匯入整個服務。若要在您的應用程式中使用此功能，您的 AWS AppSync 建構會使用 格式 `appsync.construct_name`。例如，如果我們想要製作 GraphQL API，我們會說 `new appsync.GraphqlApi(args_go_here)`。下列步驟說明了這一點。

1. 最基本的 GraphQL API 將包含 API `name` 和 `schema` 路徑的 。

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     name: 'name_of_API_in_console',
     schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema_name.graphql')),
   });
   ```
**注意**  
讓我們檢閱此程式碼片段的功能。在 範圍內`api`，我們呼叫 來建立新的 GraphQL API`appsync.GraphqlApi(scope: Construct, id: string, props: GraphqlApiProps)`。範圍為 `this`，是指目前的物件。ID 是 *API\$1ID*，其將在建立 CloudFormation 時做為 GraphQL API 的資源名稱。`GraphqlApiProps` 包含 GraphQL API `name`的 和 `schema`。`schema` 將透過搜尋`.graphql`檔案的絕對路徑 (`SchemaFile.fromAsset`) (*schema\$1name.graphql*) 來產生結構描述 (`__dirname`)。在實際案例中，您的結構描述檔案可能位於 CDK 應用程式內。  
若要使用對 GraphQL API 所做的變更，您必須重新部署應用程式。

------

## 將類型新增至結構描述
<a name="adding-schema-types"></a>

現在您已新增結構描述，您可以開始同時新增輸入和輸出類型。請注意，此處的類型不應用於真實程式碼；它們只是協助您了解程序的範例。

首先，我們會建立物件類型。在真實程式碼中，您不需要從這些類型開始。只要您遵循 GraphQL 的規則和語法，您可以隨時進行您想要的類型。

**注意**  
接下來的幾個區段將使用**結構描述編輯器**，因此請保持開啟狀態。

------
#### [ Console ]
+ 您可以使用 `type`關鍵字以及 類型的名稱來建立物件類型：

  ```
  type Type_Name_Goes_Here {}
  ```

  在類型範圍內，您可以新增代表物件特性的欄位：

  ```
  type Type_Name_Goes_Here {
    # Add fields here
  }
  ```

  範例如下：

  ```
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  ```
**注意**  
在此步驟中，我們新增了一個一般物件類型，其中包含存放為 的必要`id`欄位`ID`、存放為 `title`的欄位`String`，以及存放為 `date`的欄位`AWSDateTime`。若要查看類型和欄位清單及其用途，請參閱[結構描述](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)。若要查看純量清單及其用途，請參閱[類型參考](https://docs.aws.amazon.com/appsync/latest/devguide/type-reference.html)。

------
#### [ CLI ]

**注意**  
如果您尚未閱讀主控台版本，建議您先閱讀該版本。
+ 您可以執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html)命令來建立物件類型。

  您需要為此特定命令輸入幾個參數：

  1. 您 API `api-id`的 。

  1. `definition`或 類型的內容。在主控台範例中，這是：

     ```
     type Obj_Type_1 {
       id: ID!
       title: String
       date: AWSDateTime
     }
     ```

  1. 您輸入的 `format` 。在此範例中，我們使用 `SDL`。

  範例命令可能如下所示：

  ```
  aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Obj_Type_1{id: ID! title: String date: AWSDateTime}" --format SDL
  ```

  輸出會在 CLI 中傳回。範例如下：

  ```
  {
      "type": {
          "definition": "type Obj_Type_1{id: ID! title: String date: AWSDateTime}",
          "name": "Obj_Type_1",
          "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Obj_Type_1",
          "format": "SDL"
      }
  }
  ```
**注意**  
在此步驟中，我們新增了一個一般物件類型，其中包含存放為 的必要`id`欄位`ID`、存放為 `title`的欄位`String`，以及存放為 `date`的欄位`AWSDateTime`。若要查看類型和欄位清單及其用途，請參閱[結構描述](https://docs.aws.amazon.com//appsync/latest/devguide/schema-components.html)。若要查看純量清單及其用途，請參閱[類型參考](https://docs.aws.amazon.com/appsync/latest/devguide/type-reference.html)。  
進一步說明，您可能已意識到輸入定義直接適用於較小的類型，但無法用於新增較大的或多種類型。您可以選擇在`.graphql`檔案中新增所有項目，然後將其[做為輸入](https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters-file.html)傳遞。

------
#### [ CDK ]

**提示**  
在使用 CDK 之前，建議您檢閱 CDK 的[官方文件](https://docs.aws.amazon.com/cdk/v2/guide/home.html)以及 CDK AWS AppSync參考。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
下列步驟只會顯示用來新增特定資源之程式碼片段的一般範例。**這不是**生產程式碼中的工作解決方案。我們也假設您已經有運作中的應用程式。

若要新增類型，您需要將其新增至您的 `.graphql` 檔案。例如，主控台範例為：

```
type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}
```

您可以將類型直接新增至結構描述，就像任何其他檔案一樣。

**注意**  
若要使用對 GraphQL API 所做的變更，您必須重新部署應用程式。

------

[物件類型](https://graphql.org/learn/schema/#object-types-and-fields)具有[純量類型的](https://graphql.org/learn/schema/#scalar-types)欄位，例如字串和整數。 AWS AppSync 也可讓您除了基本 GraphQL 純量`AWSDateTime`之外，使用 等增強純量類型。此外，結尾為驚嘆號的任何欄位都是必要的。

特別是`ID`純量類型是唯一識別符，可以是 `String`或 `Int`。您可以在解析程式程式碼中控制這些項目以進行自動指派。

特殊物件類型之間有相似之處，例如 `Query`和上述範例的「一般」物件類型，因為它們都使用`type`關鍵字並被視為物件。不過，對於特殊物件類型 (`Query`、 和 `Subscription`)`Mutation`，其行為非常不同，因為它們會公開為 API 的進入點。它們也與塑造操作而非資料有關。如需詳細資訊，請參閱[查詢和變動類型](https://graphql.org/learn/schema/#the-query-and-mutation-types)。

在特殊物件類型的主題上，下一個步驟可能是新增一或多個物件，以對形狀資料執行操作。在實際案例中，每個 GraphQL 結構描述至少必須具有請求資料的根查詢類型。您可以將查詢視為 GraphQL 伺服器的其中一個進入點 （或端點）。讓我們新增查詢做為範例。

------
#### [ Console ]
+ 若要建立查詢，您可以直接將其新增至結構描述檔案，就像任何其他類型一樣。查詢需要`Query`類型和根目錄中的項目，如下所示：

  ```
  schema {
    query: Name_of_Query
  }
  
  type Name_of_Query {
    # Add field operation here
  }
  ```

  請注意，`Query`在大多數情況下，生產環境中的 *Name\$1of\$1Query* 只會被呼叫。我們建議將其保持在此值。在查詢類型中，您可以新增欄位。每個欄位都會在請求中執行 操作。因此，如果不是全部，則大多數這些欄位都會連接到解析程式。不過，在本節中，我們並不關心這一點。關於欄位操作的格式，可能如下所示：

  ```
  Name_of_Query(params): Return_Type # version with params
  Name_of_Query: Return_Type # version without params
  ```

  範例如下：

  ```
  schema {
    query: Query
  }
  
  type Query {
    getObj: [Obj_Type_1]
  }
  
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  ```
**注意**  
在此步驟中，我們新增了 `Query`類型，並將其定義在我們的`schema`根目錄中。我們的`Query`類型定義了傳回`Obj_Type_1`物件清單`getObj`的欄位。請注意， `Obj_Type_1`是上一個步驟的物件。在生產程式碼中，您的欄位操作通常會使用 這類物件所塑造的資料`Obj_Type_1`。此外， 等欄位`getObj`通常會有解析程式來執行商業邏輯。這將在不同的章節中涵蓋。  
另請注意， 會在匯出期間 AWS AppSync 自動新增結構描述根目錄，因此在技術上您不需要將其直接新增至結構描述。我們的服務會自動處理重複的結構描述。我們將這裡新增為最佳實務。

------
#### [ CLI ]

**注意**  
如果您尚未閱讀主控台版本，建議您先閱讀該版本。

1. 執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html)命令，以建立具有 `query`定義的`schema`根目錄。

   您需要為此特定命令輸入幾個參數：

   1. 您 API `api-id`的 。

   1. `definition`或 類型的內容。在主控台範例中，這是：

      ```
      schema {
        query: Query
      }
      ```

   1. 您輸入的 `format` 。在此範例中，我們使用 `SDL`。

   範例命令可能如下所示：

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "schema {query: Query}" --format SDL
   ```

   輸出會在 CLI 中傳回。範例如下：

   ```
   {
       "type": {
           "definition": "schema {query: Query}",
           "name": "schema",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```
**注意**  
請注意，如果您未在`create-type`命令中正確輸入內容，您可以執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html)命令來更新結構描述根目錄 （或結構描述中的任何類型）。在此範例中，我們將暫時變更結構描述根目錄以包含`subscription`定義。  
您需要為此特定命令輸入幾個參數：  
您 API `api-id`的 。
`type-name` 您 類型的 。在主控台範例中，這是 `schema`。
`definition`或 類型的內容。在主控台範例中，這是：  

      ```
      schema {
        query: Query
      }
      ```
新增 後的結構描述`subscription`如下所示：  

      ```
      schema {
        query: Query
        subscription: Subscription
      }
      ```
您輸入的 `format` 。在此範例中，我們使用 `SDL`。
範例命令可能如下所示：  

   ```
   aws appsync update-type --api-id abcdefghijklmnopqrstuvwxyz --type-name schema --definition "schema {query: Query subscription: Subscription}" --format SDL
   ```
輸出會在 CLI 中傳回。範例如下：  

   ```
   {
       "type": {
           "definition": "schema {query: Query subscription: Subscription}",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```
在此範例中，新增預先格式化的檔案仍然有效。

1. 執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html)命令來建立 `Query` 類型。

   您需要為此特定命令輸入幾個參數：

   1. 您 API `api-id`的 。

   1. `definition`或 類型的內容。在主控台範例中，這是：

      ```
      type Query {
        getObj: [Obj_Type_1]
      }
      ```

   1. 您輸入的 `format` 。在此範例中，我們使用 `SDL`。

   範例命令可能如下所示：

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Query {getObj: [Obj_Type_1]}" --format SDL
   ```

   輸出會在 CLI 中傳回。範例如下：

   ```
   {
       "type": {
           "definition": "Query {getObj: [Obj_Type_1]}",
           "name": "Query",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Query",
           "format": "SDL"
       }
   }
   ```
**注意**  
在此步驟中，我們新增了 `Query`類型，並將其定義在您的`schema`根目錄中。我們的`Query`類型定義了傳回`Obj_Type_1`物件清單`getObj`的欄位。  
在`schema`根碼 中`query: Query`， `query:`部分表示查詢已在您的結構描述中定義，而 `Query`部分表示實際的特殊物件名稱。

------
#### [ CDK ]

**提示**  
在使用 CDK 之前，我們建議您檢閱 CDK 的[官方文件](https://docs.aws.amazon.com/cdk/v2/guide/home.html)以及 CDK AWS AppSync參考。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
下列步驟只會顯示用來新增特定資源之程式碼片段的一般範例。這**並非**您生產程式碼中的工作解決方案。我們也假設您已經有運作中的應用程式。

您需要將查詢和結構描述根新增至 `.graphql` 檔案。我們的範例看起來像以下範例，但您會想要將其取代為實際的結構描述程式碼：

```
schema {
  query: Query
}

type Query {
  getObj: [Obj_Type_1]
}

type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}
```

您可以將類型直接新增至結構描述，就像任何其他檔案一樣。

**注意**  
更新結構描述根目錄是選用的。我們將此範例新增為最佳實務。  
若要使用對 GraphQL API 所做的變更，您必須重新部署應用程式。

------

您現在已看到建立物件和特殊物件 （查詢） 的範例。您也已了解這些如何相互連結來描述資料和操作。您可以只具有資料描述和一或多個查詢的結構描述。不過，我們希望新增另一個操作，將資料新增至資料來源。我們會新增另一個名為 的特殊物件類型`Mutation`來修改資料。

------
#### [ Console ]
+ 變動將稱為 `Mutation`。如同 `Query`，內部的欄位操作`Mutation`將描述 操作，並將連接到解析程式。此外，請注意，我們需要在`schema`根中定義它，因為它是一種特殊的物件類型。以下是變動的範例：

  ```
  schema {
    mutation: Name_of_Mutation
  }
  
  type Name_of_Mutation {
    # Add field operation here
  }
  ```

  典型的變動會在根目錄中列出，例如查詢。變動是使用`type`關鍵字和名稱來定義。*Name\$1of\$1Mutation* 通常稱為 `Mutation`，因此我們建議您以這種方式保留它。每個欄位也會執行 操作。關於欄位操作的格式，可能如下所示：

  ```
  Name_of_Mutation(params): Return_Type # version with params
  Name_of_Mutation: Return_Type # version without params
  ```

  範例如下：

  ```
  schema {
    query: Query
    mutation: Mutation
  }
  
  type Obj_Type_1 {
    id: ID!
    title: String
    date: AWSDateTime
  }
  
  type Query {
    getObj: [Obj_Type_1]
  }
  
  type Mutation {
    addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
  }
  ```
**注意**  
在此步驟中，我們新增了具有 `addObj` 欄位的`Mutation`類型。讓我們總結此欄位的功能：  

  ```
  addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
  ```
`addObj` 正在使用 `Obj_Type_1` 物件來執行 操作。這是顯而易見的，因為欄位，但語法在`: Obj_Type_1`傳回類型中證明這一點。在 中`addObj`，它接受`Obj_Type_1`來自 物件的 `title`、 `id`和 `date` 欄位做為參數。如您所見，它看起來很像方法宣告。不過，我們尚未說明方法的行為。如前所述，結構描述只會用來定義資料和操作的內容，而不是它們的運作方式。當我們建立第一個解析程式時，實作實際的商業邏輯會稍後出現。  
完成結構描述後，您可以選擇將其匯出為 `schema.graphql` 檔案。在**結構描述編輯器**中，您可以選擇**匯出結構描述**，以支援的格式下載檔案。  
另請注意， 會在匯出期間 AWS AppSync 自動新增結構描述根目錄，因此在技術上您不需要將其直接新增至結構描述。我們的服務會自動處理重複的結構描述。我們將這裡新增為最佳實務。

------
#### [ CLI ]

**注意**  
如果您尚未閱讀主控台版本，建議您先閱讀該版本。

1. 執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-type.html)命令來更新您的根結構描述。

   您需要為此特定命令輸入幾個參數：

   1. 您 API `api-id`的 。

   1. `type-name` 您 類型的 。在主控台範例中，這是 `schema`。

   1. `definition`或 類型的內容。在主控台範例中，這是：

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

   1. 您輸入的 `format` 。在此範例中，我們使用 `SDL`。

   範例命令可能如下所示：

   ```
   aws appsync update-type --api-id abcdefghijklmnopqrstuvwxyz --type-name schema --definition "schema {query: Query mutation: Mutation}" --format SDL
   ```

   輸出會在 CLI 中傳回。範例如下：

   ```
   {
       "type": {
           "definition": "schema {query: Query mutation: Mutation}",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/schema",
           "format": "SDL"
       }
   }
   ```

1. 執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-type.html)命令來建立 `Mutation` 類型。

   您需要為此特定命令輸入幾個參數：

   1. 您 API `api-id`的 。

   1. `definition`或 類型的內容。在主控台範例中，這是

      ```
      type Mutation {
        addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
      }
      ```

   1. 您輸入的 `format` 。在此範例中，我們使用 `SDL`。

   範例命令可能如下所示：

   ```
   aws appsync create-type --api-id abcdefghijklmnopqrstuvwxyz --definition "type Mutation {addObj(id: ID! title: String date: AWSDateTime): Obj_Type_1}" --format SDL
   ```

   輸出會在 CLI 中傳回。範例如下：

   ```
   {
       "type": {
           "definition": "type Mutation {addObj(id: ID! title: String date: AWSDateTime): Obj_Type_1}",
           "name": "Mutation",
           "arn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation",
           "format": "SDL"
       }
   }
   ```

------
#### [ CDK ]

**提示**  
在使用 CDK 之前，我們建議您檢閱 CDK 的[官方文件](https://docs.aws.amazon.com/cdk/v2/guide/home.html)以及 CDK AWS AppSync參考。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
下列步驟只會顯示用來新增特定資源之程式碼片段的一般範例。這**並非**您生產程式碼中的工作解決方案。我們也假設您已經有運作中的應用程式。

您需要將查詢和結構描述根新增至 `.graphql` 檔案。我們的範例看起來像以下範例，但您會想要將其取代為實際的結構描述程式碼：

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

type Obj_Type_1 {
  id: ID!
  title: String
  date: AWSDateTime
}

type Query {
  getObj: [Obj_Type_1]
}

type Mutation {
  addObj(id: ID!, title: String, date: AWSDateTime): Obj_Type_1
}
```

**注意**  
更新結構描述根目錄是選用的。我們將此範例新增為最佳實務。  
若要使用對 GraphQL API 所做的變更，您必須重新部署應用程式。

------

## 選用考量 - 使用列舉做為狀態
<a name="optional-consideration-enums"></a>

此時，您知道如何建立基本結構描述。不過，您可以新增許多項目來增加結構描述的功能。在應用程式中發現的一個常見情況是使用列舉做為狀態。您可以使用列舉來強制在呼叫時選擇一組值中的特定值。這對您知道不會長時間發生劇烈變化的事物很有用。假設我們可以新增 enum，在回應中傳回狀態碼或字串。

例如，假設我們製作的社交媒體應用程式將使用者的文章資料存放在後端。我們的結構描述包含代表個別文章資料的`Post`類型：

```
type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}
```

我們的 `Post` 將包含一個唯一的 `id`、貼文 `title`和一個名為 `date`的列舉`PostStatus`，代表應用程式處理貼文時的狀態。對於我們的操作，我們將有一個查詢，會傳回所有文章資料：

```
type Query {
  getPosts: [Post]
}
```

我們也會有一個變動，將文章新增至資料來源：

```
type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}
```

查看我們的結構描述，`PostStatus`列舉可能有數種狀態。我們可能會希望名為 `success`（已成功處理文章）、 `pending` （正在處理文章） 和 `error`（無法處理文章） 的三個基本狀態。若要新增列舉，我們可以執行下列動作：

```
enum PostStatus {
  success
  pending
  error
}
```

完整的結構描述可能如下所示：

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

type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}

type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}

type Query {
  getPosts: [Post]
}

enum PostStatus {  
  success
  pending
  error
}
```

如果使用者`Post`在應用程式中新增 ，則會呼叫 `addPost`操作來處理該資料。當連接至 的解析程式`addPost`處理資料時，它會持續更新`poststatus`具有 操作狀態的 。查詢時， `Post`將包含資料的最終狀態。請記住，我們只會描述我們希望資料在結構描述中的運作方式。我們正在假設許多有關 （解析程式） 的實作，這會實作實際的商業邏輯來處理資料以滿足請求。

## 選用考量 - 訂閱
<a name="optional-consideration-subscriptions"></a>

訂閱 in AWS AppSync 被調用為對變動的回應。您可利用結構描述之中的 `Subscription` 類型及 `@aws_subscribe()` 指令進行設定，表示哪些變動用於叫用一項以上的訂閱。如需設定訂閱的詳細資訊，請參閱[即時資料](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html)。

## 選用考量 - 關係和分頁
<a name="optional-consideration-relations-and-pagination"></a>

假設您在 DynamoDB 資料表中`Posts`存放了一百萬個資料，而且您想要傳回其中一些資料。不過，上述提供的範例查詢只會傳回所有文章。您不會想要在每次提出請求時擷取所有這些項目。反之，您會想要透過它們[進行分頁](https://graphql.org/learn/pagination/)。請對結構描述進行下列變更：
+ 在 `getPosts`欄位中，新增兩個輸入引數： `nextToken`（迭代器） 和 `limit`（迭代限制）。
+ 新增包含 `Posts`（擷取`Post`物件清單） 和 `nextToken`（迭代器） 欄位的新`PostIterator`類型。
+ 變更 ，`getPosts`使其傳回 `PostIterator` ，而不是`Post`物件清單。

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

type Post {
  id: ID!
  title: String
  date: AWSDateTime
  poststatus: PostStatus
}

type Mutation {
  addPost(id: ID!, title: String, date: AWSDateTime, poststatus: PostStatus): Post
}

type Query {
  getPosts(limit: Int, nextToken: String): PostIterator
}

enum PostStatus {
  success
  pending
  error
}

type PostIterator {
  posts: [Post]
  nextToken: String
}
```

`PostIterator` 類型可讓您傳回`Post`物件清單的一部分，以及`nextToken`用於取得下一個部分的 。在 中`PostIterator`，有一個項目清單 `Post`(`[Post]`) 以分頁字符 () 傳回`nextToken`。In AWS AppSync，這會透過解析程式連線至 Amazon DynamoDB，並自動產生為加密字符。這會將 `limit` 引數的值轉換成 `maxResults` 參數，並將 `nextToken` 引數轉換成 `exclusiveStartKey` 參數。如需 AWS AppSync 主控台中的範例和內建範本範例，請參閱[解析程式參考 (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html)。

# 連接資料來源 in AWS AppSync
<a name="attaching-a-data-source"></a>

資料來源是您 AWS 帳戶中 GraphQL APIs 可與之互動的資源。 AWS AppSync 支援多種資料來源 AWS Lambda，例如 Amazon DynamoDB、關聯式資料庫 (Amazon Aurora Serverless)、Amazon OpenSearch Service 和 HTTP 端點。An AWS AppSync API 可以設定為與多個資料來源互動，讓您能夠在單一位置彙總資料。 AWS AppSync 可以使用您帳戶中的現有 AWS 資源，或從結構描述定義代表您佈建 DynamoDB 資料表。

下一節將示範如何將資料來源連接至 GraphQL API。

## 資料來源的類型
<a name="data-source-types"></a>

現在您已在 AWS AppSync 主控台中建立結構描述，您可以將資料來源連接至該結構描述。當您最初建立 API 時，可以選擇在建立預先定義的結構描述期間佈建 Amazon DynamoDB 資料表。不過，我們不會在本節中涵蓋該選項。您可以在[啟動結構描述](https://docs.aws.amazon.com//appsync/latest/devguide/schema-launch-start.html)區段中看到此範例。

反之，我們將查看 AWS AppSync 支援的所有資料來源。為您的應用程式挑選正確的解決方案有許多因素。以下各節將為每個資料來源提供一些額外的內容。如需資料來源的一般資訊，請參閱[資料來源](https://docs.aws.amazon.com/appsync/latest/devguide/data-source-components.html)。

### Amazon DynamoDB
<a name="data-source-type-ddb"></a>

Amazon DynamoDB 是可擴展應用程式 AWS的主要儲存解決方案之一。DynamoDB 的核心元件是 **資料表**，只是資料集合。您通常會根據 `Book`或 等實體建立資料表`Author`。資料表項目資訊會儲存為**項目**，這些項目是每個項目唯一的欄位群組。完整項目代表資料庫中的資料列/記錄。例如，`Book`項目的項目可能包含 `title`和 `author`及其值。`title` 和 等個別欄位`author`稱為**屬性**，與關聯式資料庫中的資料欄值類似。

您可以猜測，資料表將用於存放應用程式的資料。 AWS AppSync 可讓您將 DynamoDB 資料表連接至 GraphQL API 以操作資料。從*前端 Web 和行動部落格*取得此[使用案例](https://aws.amazon.com/blogs/mobile/new-real-time-multi-group-app-with-aws-amplify-graphql-build-a-twitter-community-clone/)。此應用程式可讓使用者註冊社交媒體應用程式。使用者可以加入群組，並上傳廣播給其他訂閱該群組的使用者的文章。其應用程式會將使用者、文章和使用者群組資訊存放在 DynamoDB 中。GraphQL API （由 管理 AWS AppSync) 會與 DynamoDB 資料表連接。當使用者在系統進行將反映在前端的變更時，GraphQL API 會擷取這些變更並將其即時廣播給其他使用者。

### AWS Lambda
<a name="data-source-type-lam"></a>

Lambda 是一種事件驅動服務，可自動建置必要的資源，以執行程式碼作為事件的回應。Lambda 使用 **函數**，這些函數是包含程式碼、相依性和組態的群組陳述式，用於執行資源。函數會在偵測到**觸發**條件時自動執行，這是叫用函數的一組活動。觸發可以是發出 API 呼叫的應用程式、您帳戶中啟動資源 AWS 的服務等。觸發時， 函數會處理事件，這些**事件**是包含要修改之資料的 JSON 文件。

Lambda 非常適合執行程式碼，無需佈建資源即可執行。從*前端 Web 和行動部落格*取得此[使用案例](https://aws.amazon.com/blogs/mobile/building-a-graphql-api-with-java-and-aws-lambda/)。此使用案例與 DynamoDB 區段中展示的使用案例略有相似。在此應用程式中，GraphQL API 負責定義物件的操作，例如新增文章 （變動） 和擷取該資料 （查詢）。為了實作其操作的功能 （例如 `getPost ( id: String ! ) : Post`、`getPostsByAuthor ( author: String ! ) : [ Post ]`)，他們使用 Lambda 函數來處理傳入請求。在*選項 2： AWS AppSync 搭配 Lambda 解析程式*下，他們使用 AWS AppSync 服務來維護其結構描述，並將 Lambda 資料來源連結至其中一個操作。呼叫 操作時，Lambda 會與 Amazon RDS Proxy 連接，以在資料庫上執行業務邏輯。

### Amazon RDS
<a name="data-source-type-RDS"></a>

Amazon RDS 可讓您快速建置和設定關聯式資料庫。在 Amazon RDS 中，您將建立一般**資料庫執行個體**，做為雲端中隔離的資料庫環境。在此執行個體中，您將使用 **資料庫引擎**，這是實際的 RDBMS 軟體 (PostgreSQL、MySQL 等）。此服務使用 AWS基礎設施、修補和加密等安全服務，以及降低部署的管理成本，來卸載大部分後端工作。

從 Lambda 區段取得相同的[使用案例](https://aws.amazon.com/blogs/mobile/building-a-graphql-api-with-java-and-aws-lambda/)。在*選項 3： AWS AppSync 使用 Amazon RDS 解析程式*下，顯示的另一個選項是直接將 中的 GraphQL API 連結至 AWS AppSync Amazon RDS。使用[資料 API](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/data-api.html)，它們會將資料庫與 GraphQL API 建立關聯。解析程式會連接到欄位 （通常是查詢、變動或訂閱），並實作存取資料庫所需的 SQL 陳述式。當用戶端發出呼叫 欄位的請求時，解析程式會執行陳述式並傳回回應。

### Amazon EventBridge
<a name="data-source-type-eventbridge"></a>

在 EventBridge 中，您將建立**事件匯流排**，這是從您連接的服務或應用程式 (**事件來源**) 接收事件，並根據一組規則處理事件的管道。**事件**是執行環境中的一些狀態變更，而**規則**是事件的一組篩選條件。規則遵循**事件模式**或事件狀態變更的中繼資料 (id、區域、帳戶號碼、ARN (s) 等）。當事件符合事件模式時，EventBridge 會將整個管道的事件傳送至目的地服務 (**目標**)，並觸發規則中指定的動作。

EventBridge 非常適合將變更狀態的操作路由到其他一些 服務。從*前端 Web 和行動部落格*取得此[使用案例](https://aws.amazon.com/blogs/mobile/appsync-eventbridge/)。此範例描述的電子商務解決方案有數個團隊維護不同的服務。這些服務之一會在前端交付的每個步驟 （下單、進行中、運送、交付等） 為客戶提供訂單更新。不過，管理此服務的前端團隊無法直接存取排序系統資料，因為這是由個別後端團隊所維護。後端團隊的排序系統也被描述為黑色方塊，因此很難收集有關他們建構資料的方式的資訊。不過，後端團隊確實設定了一個系統，透過 EventBridge 管理的事件匯流排發佈訂單資料。為了存取來自事件匯流排的資料並將其路由到前端，前端團隊建立了指向其 GraphQL API 的新目標 AWS AppSync。他們也建立了規則，只傳送與訂單更新相關的資料。進行更新時，來自事件匯流排的資料會傳送至 GraphQL API。API 中的結構描述會處理資料，然後將其傳遞至前端。

### 無資料來源
<a name="data-source-type-none"></a>

如果您不打算使用資料來源，您可以將其設定為 `none`。雖然`none`資料來源仍明確分類為資料來源，但 不是儲存媒體。一般而言，解析程式會在某個時間點調用一或多個資料來源來處理請求。不過，在某些情況下，您可能不需要操作資料來源。將資料來源設定為 `none` 將執行請求、略過資料調用步驟，然後執行回應。

從 EventBridge 區段取得相同的[使用案例](https://aws.amazon.com/blogs/mobile/appsync-eventbridge/)。在結構描述中，變動會處理狀態更新，然後將其傳送給訂閱者。回顧解析程式的運作方式，通常至少有一個資料來源調用。不過，此案例中的資料已由事件匯流排自動傳送。這表示不需要變動來執行資料來源叫用；訂單狀態可以直接在本機處理。變動設定為 `none`，可做為沒有資料來源調用的傳遞值。然後，結構描述會填入傳送給訂閱者的資料。

### OpenSearch
<a name="data-source-type-opensearch"></a>

Amazon OpenSearch Service 是一套工具，可實作全文搜尋、資料視覺化和記錄。您可以使用此服務來查詢您上傳的結構化資料。

在此服務中，您將建立 OpenSearch 的執行個體。這些稱為**節點**。在節點中，您將新增至少一個**索引**。在概念上，索引有點像關聯式資料庫中的資料表。（不過，OpenSearch 不符合 ACID 規範，因此不應以此方式使用）。您將使用上傳到 OpenSearch 服務的資料填入索引。上傳資料時，資料將會以索引中存在的一或多個碎片編製索引。**碎片**就像索引的分割區，其中包含一些資料，可以與其他碎片分開查詢。上傳後，您的資料會建構為稱為 **文件**的 JSON 檔案。然後，您可以查詢節點以取得文件中的資料。

### HTTP 端點
<a name="data-source-type-http"></a>

您可以使用 HTTP 端點做為資料來源。 AWS AppSync 可以傳送請求到具有參數和承載等相關資訊的端點。HTTP 回應將公開給解析程式，該解析程式會在完成其 （操作） 操作後傳回最終回應。

## 新增資料來源
<a name="adding-a-data-source"></a>

如果您建立了資料來源，您可以將其連結至 AWS AppSync 服務，更具體地說是 API。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在**儀表板**中選擇您的 API。

   1. 在**側邊欄中**，選擇**資料來源**。

1. 選擇 **Create data source (建立資料來源)**。

   1. 為您的資料來源命名。您也可以提供描述，但這是選用的。

   1. 選擇您的**資料來源類型**。

   1. 對於 DynamoDB，您必須選擇您的區域，然後選擇區域中的資料表。您可以選擇建立新的一般資料表角色或匯入資料表的現有角色，以指定與資料表的互動規則。您可以啟用[版本控制](https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html)，當多個用戶端同時嘗試更新資料時，它可以為每個請求自動建立資料版本。版本控制用於保留和維護多個資料變體，以用於偵測和解決衝突。您也可以啟用自動產生結構描述，這會取得資料來源，並產生在結構描述中存取它所需的一些 CRUD、 `List`和 `Query`操作。

      對於 OpenSearch，您必須選擇您的區域，然後選擇區域中的網域 （叢集）。您可以選擇建立新的一般資料表角色或匯入資料表的現有角色，以指定與網域的互動規則。

      對於 Lambda，您必須選擇您的區域，然後選擇區域中 Lambda 函數的 ARN。您可以選擇建立新的一般資料表角色或匯入資料表的現有角色，以指定與 Lambda 函數的互動規則。

      針對 HTTP，您必須輸入 HTTP 端點。

      對於 EventBridge，您必須選擇您的區域，然後選擇區域中的事件匯流排。您可以選擇建立新的一般資料表角色或匯入資料表的現有角色，以指定與事件匯流排的互動規則。

      對於 RDS，您必須選擇您的區域，然後選擇秘密存放區 （使用者名稱和密碼）、資料庫名稱和結構描述。

      對於無，您將新增沒有實際資料來源的資料來源。這是用於在本機處理解析程式，而不是透過實際的資料來源。
**注意**  
如果您要匯入現有的角色，他們需要信任政策。如需詳細資訊，請參閱 [IAM 信任政策](#iam-trust-policy.title)。

1. 選擇**建立**。
**注意**  
或者，如果您要建立 DynamoDB 資料來源，您可以前往主控台中的**結構描述**頁面，選擇頁面頂端的**建立資源**，然後填寫預先定義的模型以轉換為資料表。在此選項中，您將填寫或匯入基本類型、設定包含分割區索引鍵的基本資料表資料，以及檢閱結構描述變更。

------
#### [ CLI ]
+ 執行 [https://docs.aws.amazon.com/cli/latest/reference/appsync/create-data-source.html](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-data-source.html)命令來建立資料來源。

  您需要為此特定命令輸入幾個參數：

  1. 您 API `api-id`的 。

  1. 資料表`name`的 。

  1. 資料來源`type`的 。視您選擇的資料來源類型而定，您可能需要輸入 `service-role-arn`和 `-config`標籤。

  範例命令可能如下所示：

  ```
   aws appsync create-data-source --api-id abcdefghijklmnopqrstuvwxyz --name data_source_name --type data_source_type --service-role-arn arn:aws:iam::107289374856:role/role_name --[data_source_type]-config {params}
  ```

------
#### [ CDK ]

**提示**  
在使用 CDK 之前，我們建議您檢閱 CDK 的[官方文件](https://docs.aws.amazon.com/cdk/v2/guide/home.html)以及 CDK AWS AppSync參考。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
下列步驟只會顯示用來新增特定資源之程式碼片段的一般範例。這**並非**您生產程式碼中的工作解決方案。我們也假設您已經有運作中的應用程式。

若要新增特定資料來源，您需要將 建構新增至堆疊檔案。您可以在這裡找到資料來源類型的清單：
+  [ DynamoDbDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.DynamoDbDataSource.html) 
+  [ EventBridgeDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.EventBridgeDataSource.html) 
+  [ HttpDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.HttpDataSource.html) 
+  [ LambdaDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.LambdaDataSource.html) 
+  [ NoneDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.NoneDataSource.html) 
+  [ OpenSearchDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.OpenSearchDataSource.html) 
+  [ RdsDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.RdsDataSource.html) 

1. 一般而言，您可能需要將匯入指令新增至您正在使用的服務。例如，它可能會遵循以下表單：

   ```
   import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
   import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
   ```

   例如，以下是您可以匯入 AWS AppSync 和 DynamoDB 服務的方式：

   ```
   import * as appsync from 'aws-cdk-lib/aws-appsync';
   import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
   ```

1. 某些像 RDS 的服務在建立資料來源 （例如，VPC 建立、角色和存取憑證） 之前，需要在堆疊檔案中進行一些額外的設定。如需詳細資訊，請參閱相關 CDK 頁面中的範例。

1. 對於大多數資料來源，特別是 AWS 服務，您將在堆疊檔案中建立新的資料來源執行個體。一般而言，這看起來會如下所示：

   ```
   const add_data_source_func = new service_scope.resource_name(scope: Construct, id: string, props: data_source_props);
   ```

   例如，以下是 Amazon DynamoDB 資料表範例：

   ```
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
     partitionKey: {
       name: 'id',
       type: dynamodb.AttributeType.STRING,
     },
     sortKey: {
       name: 'id',
       type: dynamodb.AttributeType.STRING,
     },
     tableClass: dynamodb.TableClass.STANDARD,
   });
   ```
**注意**  
大多數資料來源至少會有一個必要的道具 (**將沒有**`?`符號表示）。請參閱 CDK 文件，了解需要哪些道具。

1. 接著，您需要將資料來源連結至 GraphQL API。建議的方法是在為管道解析程式建立函數時新增它。例如，以下程式碼片段是掃描 DynamoDB 資料表中所有元素的函數：

   ```
   const add_func = new appsync.AppsyncFunction(this, 'func_ID', {
     name: 'func_name_in_console',
     add_api,
     dataSource: add_api.addDynamoDbDataSource('data_source_name_in_console', add_ddb_table),
     code: appsync.Code.fromInline(`
         export function request(ctx) {
           return { operation: 'Scan' };
         }
   
         export function response(ctx) {
           return ctx.result.items;
         }
     `),
     runtime: appsync.FunctionRuntime.JS_1_0_0,
   });
   ```

   在`dataSource`道具中，您可以呼叫 GraphQL API (`add_api`)，並使用其中一個內建方法 (`addDynamoDbDataSource`) 建立資料表與 GraphQL API 之間的關聯。引數是將存在於 AWS AppSync 主控台 (`data_source_name_in_console`在此範例中為 ) 和資料表方法 () 中的此連結名稱`add_ddb_table`。當您開始建立解析程式時，將在下一節中顯示有關此主題的更多資訊。

   有替代方法來連結資料來源。您可以在技術上`api`新增至資料表函數中的道具清單。例如，以下是步驟 3 的程式碼片段，但具有包含 `api` GraphQL API 的 props：

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     ...
   });
   
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
   
    ...
   
     api: add_api
   });
   ```

   或者，您可以分別呼叫`GraphqlApi`建構：

   ```
   const add_api = new appsync.GraphqlApi(this, 'API_ID', {
     ...
   });
   
   const add_ddb_table = new dynamodb.Table(this, 'Table_ID', {
     ...
   });
   
   const link_data_source = add_api.addDynamoDbDataSource('data_source_name_in_console', add_ddb_table);
   ```

   我們建議只在函數的道具中建立關聯。否則，您必須在 AWS AppSync 主控台中手動將解析程式函數連結至資料來源 （如果您想要繼續使用主控台值 `data_source_name_in_console`)，或在函數中以其他名稱建立個別的關聯，例如 `data_source_name_in_console_2`。這是因為道具處理資訊的方式受到限制。
**注意**  
您必須重新部署應用程式，才能查看您的變更。

------

### IAM 信任政策
<a name="iam-trust-policy"></a>

如果您為資料來源使用現有的 IAM 角色，則需要授予該角色適當的許可，以對 AWS 資源執行操作，例如在 Amazon DynamoDB 資料表`PutItem`上執行操作。您也需要修改該角色的信任政策，以允許 AWS AppSync 將其用於資源存取，如下列範例政策所示：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": "appsync.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
        }
    ]
}
```

------

您也可以將條件新增至信任政策，以視需要限制對資料來源的存取。目前， `SourceArn` 和 `SourceAccount`金鑰可用於這些條件。例如，下列政策會將對資料來源的存取限制在帳戶 `123456789012`：

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "StringEquals": {
          "aws:SourceAccount": "123456789012"
        }
      }
    }
  ]
}
```

------

或者，您可以使用下列政策`abcdefghijklmnopq`，將資料來源的存取限制為特定 API，例如 ：

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:appsync:us-west-2:123456789012:apis/abcdefghijklmnopq"
        }
      }
    }
  ]
}
```

------

您可以使用`us-east-1`下列政策，限制從特定區域存取 all AWS AppSync APIs，例如 ：

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "appsync.amazonaws.com"
      },
      "Action": "sts:AssumeRole",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:appsync:us-east-1:123456789012:apis/*"
        }
      }
    }
  ]
}
```

------

在下一節 ([設定解析程式](https://docs.aws.amazon.com//appsync/latest/devguide/resolver-config-overview.html)) 中，我們將新增解析程式商業邏輯，並將其連接到結構描述中的欄位，以處理資料來源中的資料。

如需角色政策組態的詳細資訊，請參閱《*IAM 使用者指南*》中的[修改角色](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_manage_modify.html)。

如需 AWS Lambda 解析程式 for AWS AppSync 跨帳戶存取的詳細資訊，請參閱[建置跨帳戶 AWS Lambda 解析程式 for AWS AppSync](https://aws.amazon.com/blogs/mobile/appsync-lambda-cross-account/)。

# 在 中設定解析程式 AWS AppSync
<a name="resolver-config-overview"></a>

在前幾節中，您已了解如何建立 GraphQL 結構描述和資料來源，然後在 AWS AppSync 服務中將這些結構描述和資料來源連結在一起。在您的結構描述中，您可能已在查詢和變動中建立一或多個欄位 （操作）。雖然結構描述描述了操作從資料來源請求的資料類型，但它從未實作這些操作在資料方面的行為。

操作的行為一律會在解析程式中實作，這會連結到執行操作的欄位。如需解析程式如何正常運作的詳細資訊，請參閱[解析程式](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html)頁面。

在 中 AWS AppSync，您的解析程式會繫結至執行時間，這是解析程式執行的環境。執行時間會指定您的解析程式將寫入的語言。目前支援兩種執行時間：APPSYNC\$1JS (JavaScript) 和 Apache Velocity 範本語言 (VTL)。

實作解析程式時，會遵循一般結構：
+ 在**步驟之前**：當用戶端提出請求時，所使用結構描述欄位的解析程式 （通常是您的查詢、變動、訂閱） 會傳遞請求資料。解析程式會開始處理使用步驟前處理常式的請求資料，這允許在資料通過解析程式之前執行一些預先處理操作。
+ **Function(s)**：在步驟執行之前，請求會傳遞至函數清單。清單中的第一個函數將針對資料來源執行。函數是解析程式程式碼的子集，其中包含自己的請求和回應處理常式。請求處理常式會取得請求資料，並對資料來源執行操作。回應處理常式會先處理資料來源的回應，再將其傳回清單。如果有多個函數，請求資料將傳送至清單中要執行的下一個函數。清單中的函數將依開發人員定義的順序序列執行。執行所有函數後，最終結果會傳遞至步驟後 。
+ **後步驟**：後步驟是處理常式函數，可讓您在最終函數的回應上執行一些最終操作，然後再將其傳遞至 GraphQL 回應。

此流程是管道解析程式的範例。兩個執行時間都支援管道解析程式。不過，這是管道解析程式可以執行的操作的簡化說明。此外，我們只描述一個可能的解析程式組態。如需支援的解析程式組態的詳細資訊，請參閱 APPSYNC\$1JS 的 [JavaScript 解析程式概觀](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)或 VTL 的[解析程式映射範本概觀](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-overview.html)。

如您所見，解析程式是模組化的。為了讓解析程式的元件正常運作，它們必須能夠對等其他元件的執行狀態。從[解析程式](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html)區段中，您知道解析程式中的每個元件都可以作為一組引數 (`args`、 `context`等） 傳遞有關執行狀態的重要資訊。在 中 AWS AppSync，這由 嚴格處理`context`。這是要解析之欄位資訊的容器。這可以包含來自傳遞引數、結果、授權資料、標頭資料等的所有內容。如需內容的詳細資訊，請參閱 APPSYNC\$1JS 的 [Resolver 內容物件參考](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)或 VTL 的 [Resolver 映射範本內容參考](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference.html)。

內容並非您可用來實作解析程式的唯一工具。 AWS AppSync 支援各種公用程式，可用於產生價值、處理錯誤、剖析、轉換等。您可以在[此處](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html)查看 APPSYNC\$1JS 的公用程式清單，或是 [VTL](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html) 的公用程式清單。

在下列各節中，您將了解如何在 GraphQL API 中設定解析程式。

**Topics**
+ [建立基本查詢 (JavaScript)](configuring-resolvers-js.md)
+ [建立基本查詢 (VTL)](configuring-resolvers.md)

# 建立基本查詢 (JavaScript)
<a name="configuring-resolvers-js"></a>

GraphQL 解析程式將類型結構描述中的欄位連接到資料來源。解析程式是滿足請求的機制。

Resolvers in AWS AppSync 使用 JavaScript 將 GraphQL 表達式轉換為資料來源可以使用的格式。或者，映射範本可以用 [Apache Velocity 範本語言 (VTL)](https://velocity.apache.org/engine/2.0/vtl-reference.html) 撰寫，將 GraphQL 表達式轉換為資料來源可以使用的格式。

本節說明如何使用 JavaScript 設定解析程式。[Resolver 教學課程 (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html) 區段提供如何使用 JavaScript 實作解析程式的深入教學課程。[Resolver 參考 (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-js-version.html) 區段提供可搭配 JavaScript 解析程式使用的公用程式操作說明。

我們建議您先遵循本指南，再嘗試使用上述任何教學課程。

在本節中，我們將逐步解說如何建立和設定查詢和變動的解析程式。

**注意**  
本指南假設您已建立結構描述，並且至少有一個查詢或變動。如果您要尋找訂閱 （即時資料），請參閱[本指南](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-data.html)。

在本節中，我們將提供一些設定解析程式的一般步驟，以及使用下列結構描述的範例：

```
// schema.graphql file

input CreatePostInput {
  title: String
  date: AWSDateTime
}

type Post {
  id: ID!
  title: String
  date: AWSDateTime
}

type Mutation {
  createPost(input: CreatePostInput!): Post
}

type Query {
  getPost: [Post]
}
```

## 建立基本查詢解析程式
<a name="create-basic-query-resolver-js"></a>

本節將說明如何建立基本查詢解析程式。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**結構描述**。

1. 輸入結構描述和資料來源的詳細資訊。如需詳細資訊，請參閱[設計您的結構描述](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html)和[連接資料來源](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)一節。

1. 在**結構描述**編輯器旁邊，有一個稱為**解析程式**的視窗。此方塊包含**結構描述**視窗中定義的類型和欄位清單。您可以將解析程式連接至欄位。您很可能將解析程式連接到您的欄位操作。在本節中，我們將介紹簡單的查詢組態。在**查詢**類型下，選擇查詢欄位旁的**連接**。

1. 在**連接解析程式**頁面的**解析程式類型**下，您可以選擇管道或單位解析程式。如需這些類型的詳細資訊，請參閱[解析程式](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html)。本指南將使用 `pipeline resolvers`。
**提示**  
建立管道解析程式時，您的資料來源會連接到管道函數 (s)。函數會在您建立管道解析程式本身後建立，因此此頁面中沒有設定它的選項。如果您使用的是單位解析程式，則資料來源會直接繫結至解析程式，因此您會在此頁面上設定。

   針對**解析程式執行時間**，選擇`APPSYNC_JS`啟用 JavaScript 執行時間。

1. 您可以為此 API 啟用[快取](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html)。我們建議您立即關閉此功能。選擇**建立**。

1. 在**編輯解析程式**頁面上，有一個稱為**解析程式程式碼**的程式碼編輯器，可讓您實作解析程式處理常式和回應的邏輯 （步驟前後）。如需詳細資訊，請參閱 [JavaScript 解析程式概觀](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)。
**注意**  
在我們的範例中，我們只會將請求保留空白，並將回應設定為從[內容](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)傳回最後一個資料來源結果：  

   ```
   import {util} from '@aws-appsync/utils';
   
   export function request(ctx) {
       return {};
   }
   
   export function response(ctx) {
       return ctx.prev.result;
   }
   ```

   在本節下方，有一個名為 **Functions 的**資料表。函數可讓您實作可在多個解析程式間重複使用的程式碼。您可以視需要將原始程式碼儲存為新增至解析程式的函數，而不是持續重寫或複製程式碼。

   函數構成管道操作清單的大量內容。在解析程式中使用多個函數時，您可以設定函數的順序，它們將按該順序執行。它們會在請求函數執行後和回應函數開始之前執行。

   若要新增函數，請在**函數**下選擇**新增函數**，然後選擇**建立新函數**。或者，您可能會看到**建立函數**按鈕來選擇。

   1. 選擇資料來源。這將是解析程式對其執行動作的資料來源。
**注意**  
在我們的範例中，我們正在連接 的解析程式`getPost`，它會透過 擷取`Post`物件`id`。假設我們已為此結構描述設定 DynamoDB 資料表。其分割區索引鍵設定為 `id`，且為空白。

   1. 輸入 `Function name`。

   1. 在**函數程式碼**下，您需要實作函數的行為。這可能令人困惑，但每個函數都有自己的本機請求和回應處理常式。請求會執行，然後進行資料來源調用來處理請求，然後由回應處理常式處理資料來源回應。結果會存放在[內容](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)物件中。之後，清單中的下一個函數會執行，如果是最後一個函數，則會傳遞至步驟後回應處理常式。
**注意**  
在我們的範例中，我們會將解析程式連接至 `getPost`，從資料來源取得`Post`物件清單。我們的請求函數會從我們的資料表請求資料，資料表會將其回應傳遞至內容 (ctx)，然後回應會在內容中傳回結果。 AWS AppSync的強度在於其與其他 AWS 服務的互連性。由於我們使用 DynamoDB，因此我們有[一套操作](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html)來簡化這類操作。我們也有一些其他資料來源類型的樣板範例。  
我們的程式碼如下所示：  

      ```
      import { util } from '@aws-appsync/utils';
      
      /**
       * Performs a scan on the dynamodb data source
       */
      export function request(ctx) {
        return { operation: 'Scan' };
      }
      
      /**
       * return a list of scanned post items
       */
      export function response(ctx) {
        return ctx.result.items;
      }
      ```
在此步驟中，我們新增了兩個函數：  
`request`：請求處理常式會對資料來源執行擷取操作。引數包含內容物件 (`ctx`) 或一些資料，可供執行特定操作的所有解析程式使用。例如，它可能包含授權資料、要解析的欄位名稱等。傳回陳述式會執行 [https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan](https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan)操作 （如需範例，請參閱[此處](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Scan.html))。由於我們使用 DynamoDB，因此我們可以使用該服務的一些操作。掃描會執行資料表中所有項目的基本擷取。此操作的結果會存放在內容物件中做為`result`容器，再傳遞給回應處理常式。在管道中的回應之前`request`執行 。
`response`：傳回 輸出的回應處理常式`request`。引數是更新的內容物件，而傳回陳述式是 `ctx.prev.result`。在本指南的這個階段，您可能不熟悉此值。 `ctx`是指內容物件。 `prev`是指管道中先前的操作，也就是我們的 `request`。`result` 包含解析程式在管道中移動時的結果 (s)。如果您將所有操作放在一起， `ctx.prev.result` 會傳回上次執行的操作結果，也就是請求處理常式。

   1. 完成後，請選擇**建立**。

1. 返回解析程式畫面的**函數**下，選擇**新增函數**下拉式清單，並將函數新增至函數清單。

1. 選擇**儲存**以更新解析程式。

------
#### [ CLI ]

**新增您的 函數**
+ 使用 `[create-function](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-function.html)`命令為您的管道解析程式建立 函數。

  您需要為此特定命令輸入幾個參數：

  1. 您 API `api-id`的 。

  1.  AWS AppSync 主控台中`name`函數的 。

  1. 函數將使用的資料來源名稱 `data-source-name`或 。它必須已在 AWS AppSync 服務中建立並連結至您的 GraphQL API。

  1. 函數的 `runtime`、 或 環境和語言。對於 JavaScript，名稱必須為 `APPSYNC_JS`，執行期為 `1.0.0`。

  1. 函數的 `code`、 或 請求和回應處理常式。雖然您可以手動輸入，但將其新增至 .txt 檔案 （或類似格式），然後將其做為引數傳入會更為容易。
**注意**  
我們的查詢程式碼將位於傳入為引數的檔案中：  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Performs a scan on the dynamodb data source
      */
     export function request(ctx) {
       return { operation: 'Scan' };
     }
     
     /**
      * return a list of scanned post items
      */
     export function response(ctx) {
       return ctx.result.items;
     }
     ```

  範例命令可能如下所示：

  ```
  aws appsync create-function \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --name get_posts_func_1 \
  --data-source-name table-for-posts \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file://~/path/to/file/{filename}.{fileType}
  ```

  輸出會在 CLI 中傳回。範例如下：

  ```
  {
      "functionConfiguration": {
          "functionId": "ejglgvmcabdn7lx75ref4qeig4",
          "functionArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/functions/ejglgvmcabdn7lx75ref4qeig4",
          "name": "get_posts_func_1",
          "dataSourceName": "table-for-posts",
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```
**注意**  
請務必在`functionId`某處記錄 ，因為這將用於將函數連接至解析程式。

**建立您的解析程式**
+ 執行 `[create-resolver](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html)`命令`Query`，為 建立管道函數。

  您需要為此特定命令輸入幾個參數：

  1. 您 API `api-id`的 。

  1. `type-name`結構描述中的 或特殊物件類型 （查詢、變動、訂閱）。

  1. 在您欲連接解析程式之特殊物件類型內的 `field-name`或 欄位操作。

  1. `kind`，指定單位或管道解析程式。將此設為 `PIPELINE`以啟用管道函數。

  1. 要連接到解析程式的 (`pipeline-config`或） 函數。請確定您知道函數`functionId`的值。列出順序很重要。

  1. `runtime`，也就是 `APPSYNC_JS`(JavaScript)。`runtimeVersion` 目前為 `1.0.0`。

  1. `code`，其中包含步驟處理常式前後的 。
**注意**  
我們的查詢程式碼將位於傳入為引數的檔案中：  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       const { id, ...values } = ctx.args;
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({ id }),
         attributeValues: util.dynamodb.toMapValues(values),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  範例命令可能如下所示：

  ```
  aws appsync create-resolver \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --type-name Query \
  --field-name getPost \
  --kind PIPELINE \
  --pipeline-config functions=ejglgvmcabdn7lx75ref4qeig4 \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  輸出會在 CLI 中傳回。範例如下：

  ```
  {
      "resolver": {
          "typeName": "Mutation",
          "fieldName": "getPost",
          "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation/resolvers/getPost",
          "kind": "PIPELINE",
          "pipelineConfig": {
              "functions": [
                  "ejglgvmcabdn7lx75ref4qeig4"
              ]
          },
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```

------
#### [ CDK ]

**提示**  
在使用 CDK 之前，我們建議您檢閱 CDK 的[官方文件](https://docs.aws.amazon.com/cdk/v2/guide/home.html)以及 CDK AWS AppSync參考。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
下列步驟只會顯示用來新增特定資源之程式碼片段的一般範例。這**並非**您生產程式碼中的工作解決方案。我們也假設您已經有運作中的應用程式。

基本應用程式將需要下列項目：

1. 服務匯入指令

1. 結構描述程式碼

1. 資料來源產生器

1. 函數程式碼

1. 解析程式程式碼

從[設計您的結構描述](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html)和[連接資料來源](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)區段中，我們知道堆疊檔案將包含格式的匯入指令：

```
import * as x from 'x'; # import wildcard as the 'x' keyword from 'x-service'
import {a, b, ...} from 'c'; # import {specific constructs} from 'c-service'
```

**注意**  
在先前的章節中，我們只說明了如何匯入 AWS AppSync 建構。在真實程式碼中，您必須匯入更多服務，才能執行應用程式。在我們的範例中，如果我們要建立非常簡單的 CDK 應用程式，我們至少會匯入 AWS AppSync 服務與資料來源，也就是 DynamoDB 資料表。我們還需要匯入一些額外的建構，才能部署應用程式：  

```
import * as cdk from 'aws-cdk-lib';
import * as appsync from 'aws-cdk-lib/aws-appsync';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
```
若要摘要下列各項：  
`import * as cdk from 'aws-cdk-lib';`：這可讓您定義 CDK 應用程式和建構，例如堆疊。它還包含一些實用的公用程式函數，適用於我們的應用程式，例如操作中繼資料。如果您熟悉此匯入指令，但想知道為何此處未使用 cdk 核心程式庫，請參閱[遷移](https://docs.aws.amazon.com/cdk/v2/guide/migrating-v2.html)頁面。
`import * as appsync from 'aws-cdk-lib/aws-appsync';`：這會匯入[AWS AppSync 服務](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)。
`import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';`：這會匯入 [DynamoDB 服務](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb-readme.html)。
`import { Construct } from 'constructs';`：我們需要此項目來定義根[建構](https://docs.aws.amazon.com/cdk/v2/guide/constructs.html)。

匯入的類型取決於您呼叫的服務。我們建議您查看 CDK 文件以取得範例。頁面頂端的結構描述將是 CDK 應用程式中的個別檔案，做為 `.graphql` 檔案。在堆疊檔案中，我們可以使用下列格式將其與新的 GraphQL 建立關聯：

```
const add_api = new appsync.GraphqlApi(this, 'graphQL-example', {
  name: 'my-first-api',
  schema: appsync.SchemaFile.fromAsset(path.join(__dirname, 'schema.graphql')),
});
```

**注意**  
在範圍 中`add_api`，我們使用`new`關鍵字後面接著 來新增 GraphQL API`appsync.GraphqlApi(scope: Construct, id: string , props: GraphqlApiProps)`。我們的範圍是 `this`，CFN id 是 `graphQL-example`，而我們的道具是 `my-first-api`（主控台中 API 的名稱） 和 `schema.graphql`（結構描述檔案的絕對路徑）。

若要新增資料來源，您必須先將資料來源新增至堆疊。然後，您需要使用來源特定方法將其與 GraphQL API 建立關聯。當您建立解析程式函數時，就會發生關聯。同時，讓我們使用 建立 DynamoDB 資料表的範例`dynamodb.Table`：

```
const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
  partitionKey: {
    name: 'id',
    type: dynamodb.AttributeType.STRING,
  },
});
```

**注意**  
如果我們在範例中使用此值，則會新增 CFN ID 為 `posts-table`且分割區索引鍵為 的新 DynamoDB 資料表`id (S)`。

接下來，我們需要在堆疊檔案中實作解析程式。以下是掃描 DynamoDB 資料表中所有項目的簡單查詢範例：

```
const add_func = new appsync.AppsyncFunction(this, 'func-get-posts', {
  name: 'get_posts_func_1',
  add_api,
  dataSource: add_api.addDynamoDbDataSource('table-for-posts', add_ddb_table),
  code: appsync.Code.fromInline(`
      export function request(ctx) {
        return { operation: 'Scan' };
      }

      export function response(ctx) {
        return ctx.result.items;
      }
  `),
  runtime: appsync.FunctionRuntime.JS_1_0_0,
});

new appsync.Resolver(this, 'pipeline-resolver-get-posts', {
  add_api,
  typeName: 'Query',
  fieldName: 'getPost',
  code: appsync.Code.fromInline(`
      export function request(ctx) {
        return {};
      }

      export function response(ctx) {
        return ctx.prev.result;
      }
 `),
  runtime: appsync.FunctionRuntime.JS_1_0_0,
  pipelineConfig: [add_func],
});
```

**注意**  
首先，我們建立了名為 的函數`add_func`。此建立順序可能看起來有點反直覺，但您必須在管道解析程式中建立函數，才能建立解析程式本身。函數的形式如下：  

```
AppsyncFunction(scope: Construct, id: string, props: AppsyncFunctionProps)
```
我們的範圍是 `this`，我們的 CFN ID 是 `func-get-posts`，而我們的道具包含實際的函數詳細資訊。在道具內，我們包括：  
將出現在 AWS AppSync 主控台的 `name` 函數的 (`get_posts_func_1`)。
我們先前建立的 GraphQL API (`add_api`)。
資料來源；這是我們將資料來源連結至 GraphQL API 值，然後將其連接至函數的點。我們採用我們建立的資料表 (`add_ddb_table`)，並使用其中一種`GraphqlApi`方法 (`add_api`) 將其連接到 GraphQL API ()[https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.GraphqlApi.html#addwbrdynamowbrdbwbrdatawbrsourceid-table-options](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.GraphqlApi.html#addwbrdynamowbrdbwbrdatawbrsourceid-table-options)。ID 值 (`table-for-posts`) 是主控台中 AWS AppSync 資料來源的名稱。如需來源特定方法的清單，請參閱下列頁面：  
[ DynamoDbDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.DynamoDbDataSource.html) 
 [ EventBridgeDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.EventBridgeDataSource.html) 
 [ HttpDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.HttpDataSource.html) 
 [ LambdaDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.LambdaDataSource.html) 
 [ NoneDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.NoneDataSource.html) 
 [ OpenSearchDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.OpenSearchDataSource.html) 
 [ RdsDataSource ](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync.RdsDataSource.html) 
程式碼包含函數的請求和回應處理常式，這是簡單的掃描和傳回。
執行時間指定要使用 APPSYNC\$1JS 執行時間 1.0.0 版。請注意，目前這是 APPSYNC\$1JS 唯一可用的版本。
接下來，我們需要將 函數連接至管道解析程式。我們建立解析程式的方式如下：  

```
Resolver(scope: Construct, id: string, props: ResolverProps)
```
我們的範圍是 `this`，我們的 CFN ID 是 `pipeline-resolver-get-posts`，而我們的道具包含實際的函數詳細資訊。在道具中，我們包括：  
我們先前建立的 GraphQL API (`add_api`)。
特殊物件類型名稱；這是查詢操作，因此我們只會新增值 `Query`。
欄位名稱 (`getPost`) 是 `Query`類型下結構描述中的欄位名稱。
此程式碼包含處理常式前後的 。我們的範例只會傳回函數執行其操作後，內容中的任何結果。
執行時間指定要使用 APPSYNC\$1JS 執行時間 1.0.0 版。請注意，目前這是 APPSYNC\$1JS 唯一可用的版本。
管道組態包含我們所建立函數的參考 (`add_func`)。

------

為了摘要此範例中發生的情況，您看到了實作請求和回應處理常式的 AWS AppSync 函數。函數負責與您的資料來源互動。請求處理常式將 `Scan` 操作傳送到 AWS AppSync，指示它針對 DynamoDB 資料來源執行的操作。回應處理常式傳回項目清單 (`ctx.result.items`)。然後，項目清單會自動映射至 `Post` GraphQL 類型。

## 建立基本變動解析程式
<a name="creating-basic-mutation-resolvers-js"></a>

本節將說明如何建立基本的變動解析程式。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**結構描述**。

1. 在**解析程式**區段和**變動**類型下，選擇欄位旁的**連接**。
**注意**  
在我們的範例中，我們正在連接 的解析程式`createPost`，這會將`Post`物件新增至我們的資料表。假設我們使用上一節的相同 DynamoDB 資料表。其分割區索引鍵設定為 `id`，且為空白。

1. 在**連接解析程式**頁面的**解析程式類型**下，選擇 `pipeline resolvers`。提醒您，您可以[在這裡](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-components.html)找到有關解析程式的詳細資訊。針對**解析程式執行時間**，選擇 `APPSYNC_JS`以啟用 JavaScript 執行時間。

1. 您可以為此 API 啟用[快取](https://docs.aws.amazon.com/appsync/latest/devguide/enabling-caching.html)。我們建議您立即關閉此功能。選擇**建立**。

1. 選擇**新增函數**，然後選擇**建立新函數**。或者，您可能會看到**建立函數**按鈕來選擇。

   1. 選擇您的資料來源。這應該是您要使用變動操作資料的來源。

   1. 輸入 `Function name`。

   1. 在**函數程式碼**下，您需要實作函數的行為。這是一個變動，因此請求最好會對調用的資料來源執行一些狀態變更操作。結果將由回應函數處理。
**注意**  
`createPost` 正在新增或 "putting" 資料表`Post`中的新 ，並將我們的參數做為資料。我們可以新增如下內容：  

      ```
      import { util } from '@aws-appsync/utils';
      
      /**
       * Sends a request to `put` an item in the DynamoDB data source
       */
      export function request(ctx) {
        return {
          operation: 'PutItem',
          key: util.dynamodb.toMapValues({id: util.autoId()}),
          attributeValues: util.dynamodb.toMapValues(ctx.args.input),
        };
      }
      
      /**
       * returns the result of the `put` operation
       */
      export function response(ctx) {
        return ctx.result;
      }
      ```
在此步驟中，我們也新增了 `request`和 `response`函數：  
`request`：請求處理常式接受內容做為引數。請求處理常式傳回陳述式會執行 [https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-putitem](https://docs.aws.amazon.com//appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-putitem)命令，這是內建的 DynamoDB 操作 （如需範例，請參閱[此處](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-2.html)或[此處](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/WorkingWithItems.html#WorkingWithItems.WritingData))。`PutItem` 命令會採用分割區`key`值 （由 自動產生`util.autoid()`) 並從內容引數輸入 `attributes` （這些是我們將在請求中傳遞的值），將`Post`物件新增至 DynamoDB 資料表。`key` 是 `id`，而 `attributes`是 `date`和 `title` 欄位引數。它們都是透過[https://docs.aws.amazon.com//appsync/latest/devguide/dynamodb-helpers-in-util-dynamodb-js.html#utility-helpers-in-toMap-js](https://docs.aws.amazon.com//appsync/latest/devguide/dynamodb-helpers-in-util-dynamodb-js.html#utility-helpers-in-toMap-js)協助程式預先格式化，以使用 DynamoDB 資料表。
`response`：回應接受更新的內容，並傳回請求處理常式的結果。

   1. 完成後選擇**建立**。

1. 返回解析程式畫面的**函數**下，選擇**新增函數**下拉式清單，並將函數新增至函數清單。

1. 選擇**儲存**以更新解析程式。

------
#### [ CLI ]

**新增您的 函數**
+ 使用 `[create-function](https://docs.aws.amazon.com/cli/latest/reference/appsync/create-function.html)`命令為您的管道解析程式建立 函數。

  您需要為此特定命令輸入幾個參數：

  1. 您 API `api-id`的 。

  1.  AWS AppSync 主控台中`name`函數的 。

  1. `data-source-name`或 函數將使用的資料來源名稱。它必須已在 AWS AppSync 服務中建立並連結至您的 GraphQL API。

  1. 函數的 `runtime`、 或 環境和語言。對於 JavaScript，名稱必須為 `APPSYNC_JS`，執行期為 `1.0.0`。

  1. 函數的 `code`、 或 請求和回應處理常式。雖然您可以手動輸入，但將其新增至 .txt 檔案 （或類似格式），然後將其做為引數傳入會更為容易。
**注意**  
我們的查詢程式碼將位於傳入為引數的檔案中：  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({id: util.autoId()}),
         attributeValues: util.dynamodb.toMapValues(ctx.args.input),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  範例命令可能如下所示：

  ```
  aws appsync create-function \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --name add_posts_func_1 \
  --data-source-name table-for-posts \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  輸出會在 CLI 中傳回。範例如下：

  ```
  {
      "functionConfiguration": {
          "functionId": "vulcmbfcxffiram63psb4dduoa",
          "functionArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/functions/vulcmbfcxffiram63psb4dduoa",
          "name": "add_posts_func_1",
          "dataSourceName": "table-for-posts",
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output foes here"
      }
  }
  ```
**注意**  
請務必在`functionId`某處記錄 ，因為這將用於將函數連接至解析程式。

**建立您的解析程式**
+ `Mutation` 執行 `[create-resolver](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html)`命令來建立 的管道函數。

  您需要為此特定命令輸入幾個參數：

  1. 您 API `api-id`的 。

  1. 結構描述中的 `type-name`或特殊物件類型 （查詢、變動、訂閱）。

  1. 在您欲連接解析程式之特殊物件類型內的 `field-name`或 欄位操作。

  1. `kind`，指定單位或管道解析程式。將此設為 `PIPELINE`以啟用管道函數。

  1. 要連接到解析程式的 `pipeline-config`（或） 函數。請確定您知道函數`functionId`的值。列出 的順序很重要。

  1. `runtime`，也就是 `APPSYNC_JS`(JavaScript)。`runtimeVersion` 目前為 `1.0.0`。

  1. `code`，其中包含步驟前後的 。
**注意**  
我們的查詢程式碼將位於傳入為引數的檔案中：  

     ```
     import { util } from '@aws-appsync/utils';
     
     /**
      * Sends a request to `put` an item in the DynamoDB data source
      */
     export function request(ctx) {
       const { id, ...values } = ctx.args;
       return {
         operation: 'PutItem',
         key: util.dynamodb.toMapValues({ id }),
         attributeValues: util.dynamodb.toMapValues(values),
       };
     }
     
     /**
      * returns the result of the `put` operation
      */
     export function response(ctx) {
       return ctx.result;
     }
     ```

  範例命令可能如下所示：

  ```
  aws appsync create-resolver \
  --api-id abcdefghijklmnopqrstuvwxyz \
  --type-name Mutation \
  --field-name createPost \
  --kind PIPELINE \
  --pipeline-config functions=vulcmbfcxffiram63psb4dduoa \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0 \
  --code file:///path/to/file/{filename}.{fileType}
  ```

  輸出會在 CLI 中傳回。範例如下：

  ```
  {
      "resolver": {
          "typeName": "Mutation",
          "fieldName": "createPost",
          "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Mutation/resolvers/createPost",
          "kind": "PIPELINE",
          "pipelineConfig": {
              "functions": [
                  "vulcmbfcxffiram63psb4dduoa"
              ]
          },
          "maxBatchSize": 0,
          "runtime": {
              "name": "APPSYNC_JS",
              "runtimeVersion": "1.0.0"
          },
          "code": "Code output goes here"
      }
  }
  ```

------
#### [ CDK ]

**提示**  
在使用 CDK 之前，我們建議您檢閱 CDK 的[官方文件](https://docs.aws.amazon.com/cdk/v2/guide/home.html)以及 CDK AWS AppSync參考。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
下列步驟只會顯示用來新增特定資源之程式碼片段的一般範例。這**並非**您生產程式碼中的工作解決方案。我們也假設您已經有運作中的應用程式。
+ 若要進行變動，假設您在同一個專案中，您可以將它新增至堆疊檔案，例如查詢。以下是變動的修改函數和解析程式，會將新的 新增至`Post`資料表：

  ```
  const add_func_2 = new appsync.AppsyncFunction(this, 'func-add-post', {
    name: 'add_posts_func_1',
    add_api,
    dataSource: add_api.addDynamoDbDataSource('table-for-posts-2', add_ddb_table),
        code: appsync.Code.fromInline(`
            export function request(ctx) {
              return {
                operation: 'PutItem',
                key: util.dynamodb.toMapValues({id: util.autoId()}),
                attributeValues: util.dynamodb.toMapValues(ctx.args.input),
              };
            }
  
            export function response(ctx) {
              return ctx.result;
            }
        `), 
    runtime: appsync.FunctionRuntime.JS_1_0_0,
  });
  
  new appsync.Resolver(this, 'pipeline-resolver-create-posts', {
    add_api,
    typeName: 'Mutation',
    fieldName: 'createPost',
        code: appsync.Code.fromInline(`
            export function request(ctx) {
              return {};
            }
  
            export function response(ctx) {
              return ctx.prev.result;
            }
        `),
    runtime: appsync.FunctionRuntime.JS_1_0_0,
    pipelineConfig: [add_func_2],
  });
  ```
**注意**  
由於此變動和查詢結構類似，我們只會說明我們為了進行變動所做的變更。  
在 函數中，我們將 CFN ID 變更為 `func-add-post`，並將名稱變更為 `add_posts_func_1` ，以反映我們將`Posts`新增至資料表的事實。在資料來源中，我們在 AWS AppSync 主控台中與資料表 (`add_ddb_table`) 建立新的關聯，`table-for-posts-2`因為 `addDynamoDbDataSource`方法需要它。請記住，這個新的關聯仍在使用先前建立的相同資料表，但我們現在在 AWS AppSync 主控台中有兩個與其連線：一個用於查詢 ，`table-for-posts`另一個用於變動 `table-for-posts-2`。程式碼已變更為新增 ，`Post`方法是自動產生其`id`值，並接受用戶端對其餘欄位的輸入。  
在解析程式中，我們將 ID 值變更為 `pipeline-resolver-create-posts`，以反映我們將`Posts`新增至資料表的事實。為了反映結構描述中的變動，類型名稱已變更為 `Mutation`，而名稱為 `createPost`。管道組態已設定為我們的新變動函數 `add_func_2`。

------

為了摘要此範例中發生的情況， AWS AppSync 會自動將 欄位中定義的引數`createPost`從 GraphQL 結構描述轉換為 DynamoDB 操作。此範例使用 金鑰在 DynamoDB 中存放記錄`id`，該金鑰是使用我們的 `util.autoId()` 協助程式自動建立的。您從 AWS AppSync 主控台提出的請求或其他方式傳遞到內容引數 (`ctx.args.input`) 的所有其他欄位都會儲存為資料表的屬性。金鑰和屬性都會使用 `util.dynamodb.toMapValues(values)` 協助程式自動映射至相容的 DynamoDB 格式。

AWS AppSync 也支援用於編輯解析程式的測試和偵錯工作流程。您可以使用模擬`context`物件來查看範本的轉換值，然後再叫用它。或者，您可以在執行查詢時以互動方式檢視對資料來源的完整請求。如需詳細資訊，請參閱[測試和偵錯解析程式 (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/test-debug-resolvers-js.html) 和[監控和記錄](https://docs.aws.amazon.com/appsync/latest/devguide/monitoring.html#aws-appsync-monitoring)。

## 進階解析程式
<a name="advanced-resolvers-js"></a>

如果您遵循[設計結構描述](designing-your-schema.md#aws-appsync-designing-your-schema)中的選用分頁區段，您仍然需要將解析程式新增至您的請求，才能使用分頁。我們的範例使用稱為 的查詢分頁`getPosts`，一次只傳回請求的一部分物件。解析程式在該欄位上的程式碼可能如下所示：

```
/**
 * Performs a scan on the dynamodb data source
 */
export function request(ctx) {
  const { limit = 20, nextToken } = ctx.args;
  return { operation: 'Scan', limit, nextToken };
}

/**
 * @returns the result of the `put` operation
 */
export function response(ctx) {
  const { items: posts = [], nextToken } = ctx.result;
  return { posts, nextToken };
}
```

在請求中，我們會傳入請求的內容。我們的 `limit`是 *20*，這表示我們在第一個查詢`Posts`中傳回最多 20 個。我們的`nextToken`游標會固定為資料來源中的第一個`Post`項目。這些會傳遞給 args。然後，請求會執行從第一個`Post`到掃描限制數量的掃描。資料來源會將結果存放在內容中，該內容會傳遞給回應。回應會傳回`Posts`其擷取的 ，然後將 `nextToken` 設定為限制之後`Post`的項目。下一個請求會傳送到 以執行完全相同的物件，但在第一個查詢後立即從位移開始。請記住，這些類型的請求是依序完成的，而不是平行的。

# 測試和偵錯解析程式 in AWS AppSync (JavaScript)
<a name="test-debug-resolvers-js"></a>

AWS AppSync 會對資料來源在 GraphQL 欄位上執行解析程式。使用管道解析程式時， 函數會與您的資料來源互動。如 [JavaScript 解析程式概觀](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html)中所述， 函數會使用以 JavaScript 撰寫並在`APPSYNC_JS`執行時間執行的請求和回應處理常式，與資料來源通訊。這可讓您在與資料來源通訊之前和之後提供自訂邏輯和條件。

為了協助開發人員寫入、測試和偵錯這些解析程式， AWS AppSync 主控台也提供工具來建立 GraphQL 請求和回應，並將模擬資料縮減至個別欄位解析程式。此外，您可以在 AWS AppSync 主控台中執行查詢、變動和訂閱，並查看來自 Amazon CloudWatch 的整個請求的詳細日誌串流。這包括來自資料來源的結果。

## 使用模擬資料進行測試
<a name="testing-with-mock-data-js"></a>

叫用 GraphQL 解析程式時，會包含物件`context`，其中包含請求的相關資訊。其中包括用戶端引數、身分資訊，以及父 GraphQL 欄位的資料。它也會存放資料來源的結果，可用於回應處理常式。如需此結構和程式設計時要使用之可用協助程式公用程式的詳細資訊，請參閱[解析程式內容物件參考](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html)。

寫入或編輯解析程式函數時，您可以將*模擬*或*測試內容*物件傳遞至主控台編輯器。這可讓您查看請求和回應處理常式如何評估，而不會實際針對資料來源執行。例如您可傳送測試 `firstname: Shaggy` 引數，了解該引數在範本程式碼之中使用 `ctx.args.firstname` 時如何進行評估。您也可以測試任何公用程式協助程式的評估，例如 `util.autoId()` 或 `util.time.nowISO8601()`。

### 測試解析程式
<a name="test-a-resolver-js"></a>

此範例將使用 AWS AppSync 主控台來測試解析程式。

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在 **Sidebar** 中，選擇**函數**。

1. 選擇現有的 函數。

1. 在**更新函數**頁面頂端，選擇**選取測試內容**，然後選擇**建立新內容**。

1. 選取範例內容物件，或在下面的**設定測試內容**視窗中手動填入 JSON。

1. 輸入**文字內容名稱**。

1. 選擇 **Save (儲存)** 按鈕。

1. 若要使用此項模擬的內容物件評估解析程式，選擇 **Run Test (執行測試)** 按鈕。

如需更實際的範例，假設您有一個應用程式存放的 GraphQL 類型`Dog`，該類型使用物件的自動 ID 產生，並將它們存放在 Amazon DynamoDB 中。您也想要從 GraphQL 變動的引數寫入一些值，並僅允許特定使用者查看回應。下列程式碼片段顯示結構描述的外觀：

```
type Dog {
  breed: String
  color: String
}

type Mutation {
  addDog(firstname: String, age: Int): Dog
}
```

您可以撰寫 an AWS AppSync 函數，並將其新增至您的`addDog`解析程式來處理變動。若要測試您的 AWS AppSync 函數，您可以填入內容物件，如下列範例所示。下列引數來自 `name` 及 `age`，以及將 `username` 填入 `identity` 物件之中的用戶端：

```
{
    "arguments" : {
        "firstname": "Shaggy",
        "age": 4
    },
    "source" : {},
    "result" : {
        "breed" : "Miniature Schnauzer",
        "color" : "black_grey"
    },
    "identity": {
        "sub" : "uuid",
        "issuer" : " https://cognito-idp.{region}.amazonaws.com/{userPoolId}",
        "username" : "Nadia",
        "claims" : { },
        "sourceIp" :[  "x.x.x.x" ],
        "defaultAuthStrategy" : "ALLOW"
    }
}
```

您可以使用下列程式碼測試您的 AWS AppSync 函數：

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({ id: util.autoId() }),
    attributeValues: util.dynamodb.toMapValues(ctx.args),
  };
}

export function response(ctx) {
  if (ctx.identity.username === 'Nadia') {
    console.log("This request is allowed")
    return ctx.result;
  }
  util.unauthorized();
}
```

評估的請求和回應處理常式具有來自測試內容物件的資料，以及來自 產生的值`util.autoId()`。此外，若您將 `username` 變更為 `Nadia` 以外的值，將不會傳回結果，因為授權檢查將會失敗。如需精細存取控制的詳細資訊，請參閱[授權使用案例](security-authorization-use-cases.md#aws-appsync-security-authorization-use-cases)。

### 使用 AWS AppSync 的 APIs測試請求和回應處理常式
<a name="testing-with-appsync-api-js"></a>

您可以使用 `EvaluateCode` API 命令，以模擬資料遠端測試程式碼。若要開始使用 命令，請確定您已將 `appsync:evaluateMappingCode`許可新增至政策。例如：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appsync:evaluateCode",
            "Resource": "arn:aws:appsync:us-east-1:111122223333:*"
        }
    ]
}
```

------

您可以使用 [AWS CLI](https://aws.amazon.com/cli/)或 [AWS SDKs](https://aws.amazon.com/tools/) 來利用 命令。例如，從上一節取得結構描述及其 AWS AppSync `Dog` 函數請求和回應處理常式。在本機工作站上使用 CLI，將程式碼儲存到名為 的檔案`code.js`，然後將`context`物件儲存到名為 的檔案`context.json`。從您的 shell 執行下列命令：

```
$ aws appsync evaluate-code \
  --code file://code.js \
  --function response \
  --context file://context.json \
  --runtime name=APPSYNC_JS,runtimeVersion=1.0.0
```

回應包含 ，`evaluationResult`其中包含處理常式傳回的承載。它還包含 物件，該`logs`物件會保留您的處理常式在評估期間產生的日誌清單。這可讓您輕鬆地偵錯程式碼執行，並查看評估的相關資訊，以協助故障診斷。例如：

```
{
    "evaluationResult": "{\"breed\":\"Miniature Schnauzer\",\"color\":\"black_grey\"}",
    "logs": [
        "INFO - code.js:13:5: \"This request is allowed\""
    ]
}
```

`evaluationResult` 可以剖析為 JSON，其提供：

```
{
  "breed": "Miniature Schnauzer",
  "color": "black_grey"
}
```

使用 SDK，您可以輕鬆整合來自您最愛測試套件的測試，以驗證處理常式的行為。我們建議您使用 [Jest 測試架構](https://jestjs.io/)建立測試，但任何測試套件都可以運作。下列程式碼片段顯示假設性驗證執行。請注意，我們預期評估回應是有效的 JSON，因此我們使用 從字串回應`JSON.parse`擷取 JSON：

```
const AWS = require('aws-sdk')
const fs = require('fs')
const client = new AWS.AppSync({ region: 'us-east-2' })
const runtime = {name:'APPSYNC_JS',runtimeVersion:'1.0.0')

test('request correctly calls DynamoDB', async () => {
  const code = fs.readFileSync('./code.js', 'utf8')
  const context = fs.readFileSync('./context.json', 'utf8')
  const contextJSON = JSON.parse(context)
  
  const response = await client.evaluateCode({ code, context, runtime, function: 'request' }).promise()
  const result = JSON.parse(response.evaluationResult)
  
  expect(result.key.id.S).toBeDefined()
  expect(result.attributeValues.firstname.S).toEqual(contextJSON.arguments.firstname)
})
```

 這會產生下列結果：

```
Ran all test suites.
> jest

PASS ./index.test.js
✓ request correctly calls DynamoDB (543 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 totalTime: 1.511 s, estimated 2 s
```

## 偵錯即時查詢
<a name="debugging-a-live-query-js"></a>

end-to-end測試和記錄無法用來偵錯生產應用程式。 AWS AppSync 可讓您使用 Amazon CloudWatch 記錄錯誤和完整請求詳細資訊。此外，您可以使用 AWS AppSync 主控台來測試 GraphQL 查詢、變動和訂閱，以及將每個請求的即時串流日誌資料傳回查詢編輯器以進行即時偵錯。針對訂閱，日誌會顯示連線時間資訊。

若要執行此操作，您需要事先啟用 Amazon CloudWatch logs，如[監控和記錄](monitoring.md#aws-appsync-monitoring)中所述。接著，在 AWS AppSync 主控台中，選擇**查詢**索引標籤，然後輸入有效的 GraphQL 查詢。在右下角區段中，按一下並拖曳**日誌**視窗以開啟日誌檢視。在頁面頂端，選擇執行箭頭圖示來執行您的 GraphQL 查詢。操作的完整請求和回應日誌會在幾分鐘後串流到本節，您可以在 主控台中檢視它們。

# 設定和使用管道解析程式 in AWS AppSync (JavaScript)
<a name="pipeline-resolvers-js"></a>

AWS AppSync 會在 GraphQL 欄位上執行解析程式。在某些情況下，應用程式需要執行多個操作，才能解析單一 GraphQL 欄位。透過管道解析程式，開發人員現在可以編寫稱為 Functions 的操作，並依序執行這些操作。在像是以需要先執行授權檢查才能擷取欄位資料的情況中，就很適合使用管道解析程式。

如需 JavaScript 管道解析程式架構的詳細資訊，請參閱 [JavaScript 解析程式概觀](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-overview-js.html#anatomy-of-a-pipeline-resolver-js)。

## 步驟 1：建立管道解析程式
<a name="create-a-pipeline-resolver-js"></a>

在 AWS AppSync 主控台中，前往**結構描述**頁面。

儲存下列結構描述：

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

type Mutation {
    signUp(input: Signup): User
}

type Query {
    getUser(id: ID!): User
}

input Signup {
    username: String!
    email: String!
}

type User {
    id: ID!
    username: String
    email: AWSEmail
}
```

我們將將管道解析程式連接到 **Mutation** 類型的 **signUp** 欄位。在右側的**變動**類型中，選擇`signUp`變動欄位旁的**連接**。將解析程式設定為 `pipeline resolver`和`APPSYNC_JS`執行時間，然後建立解析程式。

我們的管道解析程式會註冊使用者，此註冊的第一步是驗證電子郵件地址輸入，然後在系統中儲存此位使用者。我們將封裝 **validateEmail** 函數內的電子郵件驗證，以及在 **saveUser** 函數內儲存使用者。**validateEmail** 函數會先執行，而當電子郵件驗證有效時，**saveUser** 函數就會接著執行。

執行流程如下：

1. Mutation.signUp 解析程式請求處理常式

1. validateEmail 函數

1. saveUser 函數

1. Mutation.signUp 解析程式回應處理常式

由於我們可能會在 API 上的其他解析程式中重複使用 **validateEmail** 函數，因此我們希望避免存取 ，`ctx.args`因為這些函數會從一個 GraphQL 欄位變更為另一個欄位。反之，我們可以使用 `ctx.stash` 來存放 `signUp(input: Signup)` 輸入欄位引數所傳遞的電子郵件屬性。

取代您的請求和回應函數，以更新您的解析程式程式碼：

```
export function request(ctx) {
    ctx.stash.email = ctx.args.input.email
    return {};
}

export function response(ctx) {
    return ctx.prev.result;
}
```

選擇**建立**或**儲存**以更新解析程式。

## 步驟 2：建立 函數
<a name="create-a-function-js"></a>

在管道解析程式頁面的**函數**區段中，按一下**新增函數**，然後按一下**建立新函數**。您也可以在不經過解析程式頁面的情況下建立函數；若要這樣做，請在 AWS AppSync 主控台中前往**函數**頁面。選擇 **Create function (建立函數)** 按鈕。讓我們來建立可檢查電子郵件是否有效且來源是特定網域的函數。如果電子郵件無效，則該函數會引發錯誤。否則，它會轉送任何獲予的任何輸入。

請確定您已建立 **NONE** 類型的資料來源。在資料來源**名稱清單中選擇此資料來源**。針對**函數名稱**，在 中輸入 `validateEmail`。在**函數程式碼**區域中，使用此程式碼片段覆寫所有項目：

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  const { email } = ctx.stash;
  const valid = util.matches(
    '^[a-zA-Z0-9_.+-]+@(?:(?:[a-zA-Z0-9-]+\.)?[a-zA-Z]+\.)?(myvaliddomain)\.com',
    email
  );
  if (!valid) {
    util.error(`"${email}" is not a valid email.`);
  }

  return { payload: { email } };
}

export function response(ctx) {
  return ctx.result;
}
```

檢閱您的輸入，然後選擇**建立**。我們已建立我們 **validateEmail** 函數。重複這些步驟，使用下列程式碼建立 **saveUser** 函數 （為了簡單起見，我們使用 **NONE** 資料來源，並假裝使用者在函數執行後已儲存在系統中。)：

```
import { util } from '@aws-appsync/utils';

export function request(ctx) {
  return ctx.prev.result;
}

export function response(ctx) {
  ctx.result.id = util.autoId();
  return ctx.result;
}
```

我們剛建立了 **saveUser** 函數。

## 步驟 3：將函數新增至管道解析程式
<a name="adding-a-function-to-a-pipeline-resolver-js"></a>

我們的函數應該會自動新增至我們剛建立的管道解析程式。如果不是這種情況，或者您透過函數頁面建立**函數**，您可以按一下`signUp`解析程式頁面上的新增**函數**來連接函數。將 **validateEmail** 和 **saveUser** 函數新增至解析程式。**validateEmail** 函數應該放在 **saveUser** 函數之前。當您新增更多函數時，您可以使用**上下****移動**選項來重組函數的執行順序。檢閱您的變更，然後選擇**儲存**。

## 步驟 4：執行查詢
<a name="running-a-query-js"></a>

在 AWS AppSync 主控台中，前往**查詢**頁面。在瀏覽器中，請確定您使用的是變動。如果不是，請在下拉式清單`Mutation`中選擇 ，然後選擇 `+`。輸入下列查詢：

```
mutation {
  signUp(input: {email: "nadia@myvaliddomain.com", username: "nadia"}) {
    id
    username
  }
}
```

這應該會傳回如下內容：

```
{
  "data": {
    "signUp": {
      "id": "256b6cc2-4694-46f4-a55e-8cb14cc5d7fc",
      "username": "nadia"
    }
  }
}
```

我們已使用管道解析程式成功註冊我們的使用者，並完成輸入電子郵件的驗證。

# 建立基本查詢 (VTL)
<a name="configuring-resolvers"></a>

**注意**  
我們現在主要支援 APPSYNC\$1JS 執行期及其文件。請考慮[在此處](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html)使用 APPSYNC\$1JS 執行期及其指南。

GraphQL 解析程式將類型結構描述中的欄位連接到資料來源。解析程式是滿足請求的機制。 AWS AppSync 可以從結構描述自動建立和連接解析程式，或從現有資料表建立結構描述並連接解析程式，而無需撰寫任何程式碼。

Resolvers in AWS AppSync 使用 JavaScript 將 GraphQL 表達式轉換為資料來源可以使用的格式。或者，映射範本可以用 [Apache Velocity 範本語言 (VTL)](https://velocity.apache.org/engine/2.0/vtl-reference.html) 撰寫，將 GraphQL 表達式轉換為資料來源可以使用的格式。

本節將說明如何使用 VTL 設定解析程式。您可以在[解析程式映射範本程式設計指南中找到編寫解析程式的教學風格程式設計指南](resolver-mapping-template-reference-programming-guide.md#aws-appsync-resolver-mapping-template-reference-programming-guide)，以及可在[解析程式映射範本內容參考](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference)中找到程式設計時使用的協助程式公用程式。 AWS AppSync 也有內建測試和偵錯流程，可讓您從頭開始編輯或撰寫時使用。如需詳細資訊，請參閱[測試和偵錯解析程式](test-debug-resolvers.md#aws-appsync-test-debug-resolvers)。

我們建議您先遵循本指南，再嘗試使用任何上述教學課程。

在本節中，我們將逐步解說如何建立解析程式、為變動新增解析程式，以及使用進階組態。

## 建立您的第一個解析程式
<a name="create-your-first-resolver"></a>

遵循先前章節的範例，第一個步驟是為您的 `Query` 類型建立解析程式。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**結構描述**。

1. 在頁面右側，有一個稱為**解析程式**的視窗。此方塊包含頁面左側**結構描述**視窗中定義的類型和欄位清單。您可以將解析程式連接至欄位。例如，在**查詢**類型下，選擇 `getTodos` 欄位旁的**連接**。

1. 在**建立解析程式**頁面上，選擇您在[連接資料來源指南中建立的資料來源](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)。在**設定映射範本**視窗中，您可以使用右側的下拉式清單選擇一般請求和回應映射範本，或自行撰寫。
**注意**  
將請求映射範本與回應映射範本配對稱為單位解析程式。單位解析程式通常用於執行輪換操作；我們建議僅將它們用於具有少量資料來源的單一操作。對於更複雜的操作，我們建議使用管道解析程式，其可以依序使用多個資料來源執行多個操作。  
如需請求與回應映射範本之間差異的詳細資訊，請參閱[單位解析程式](https://docs.aws.amazon.com//appsync/latest/devguide/resolver-mapping-template-reference-overview.html#unit-resolvers)。  
如需使用管道解析程式的詳細資訊，請參閱[管道解析程式](pipeline-resolvers.md#aws-appsync-pipeline-resolvers)。

1. 對於常見的使用案例， AWS AppSync 主控台具有內建範本，可用於從資料來源取得項目 （例如，所有項目查詢、個別查詢等）。例如，在設計`getTodos`沒有分頁的[結構](designing-your-schema.md#aws-appsync-designing-your-schema)描述的簡單版本上，列出項目的請求映射範本如下所示：

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

1. 您一律需要回應映射範本來隨附請求。主控台為清單提供具有下列傳遞值的預設值：

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

   在這個範例中，項目清單的 `context` 物件 (別名為 `$ctx`) 為 `$context.result.items` 格式。如果您的 GraphQL 操作傳回單一項目，則會是 `$context.result`。 AWS AppSync 提供常見操作的協助程式函數，例如先前列出的`$util.toJson`函數，以正確格式化回應。如需函數的完整清單，請參閱[解析程式映射範本公用程式參考](resolver-util-reference.md#aws-appsync-resolver-mapping-template-util-reference)。

1. 選擇**儲存解析程式**。

------
#### [ API ]

1. 呼叫 [https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html](https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html) API 來建立解析程式物件。

1. 您可以呼叫 [https://docs.aws.amazon.com/appsync/latest/APIReference/API_UpdateResolver.html](https://docs.aws.amazon.com/appsync/latest/APIReference/API_UpdateResolver.html) API 來修改解析程式的欄位。

------
#### [ CLI ]

1. 執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html)命令來建立解析程式。

   您需要為此特定命令輸入 6 個參數：

   1. 您 API `api-id`的 。

   1. 您想要在結構描述中修改`type-name`的類型 。在主控台範例中，這是 `Query`。

   1. 您要在類型中修改的欄位`field-name`的 。在主控台範例中，這是 `getTodos`。

   1. 您在連接資料來源指南中建立`data-source-name`的資料來源的 。 [https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)

   1. `request-mapping-template`，這是請求的內文。在主控台範例中，這是：

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

   1. `response-mapping-template`，這是回應的內文。在主控台範例中，這是：

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

   範例命令可能如下所示：

   ```
   aws appsync create-resolver --api-id abcdefghijklmnopqrstuvwxyz --type-name Query --field-name getTodos --data-source-name TodoTable --request-mapping-template "{ "version" : "2017-02-28", "operation" : "Scan", }" --response-mapping-template ""$"util.toJson("$"ctx.result.items)"
   ```

   輸出會在 CLI 中傳回。範例如下：

   ```
   {
       "resolver": {
           "kind": "UNIT",
           "dataSourceName": "TodoTable",
           "requestMappingTemplate": "{ version : 2017-02-28, operation : Scan, }",
           "resolverArn": "arn:aws:appsync:us-west-2:107289374856:apis/abcdefghijklmnopqrstuvwxyz/types/Query/resolvers/getTodos",
           "typeName": "Query",
           "fieldName": "getTodos",
           "responseMappingTemplate": "$util.toJson($ctx.result.items)"
       }
   }
   ```

1. 若要修改解析程式的欄位和/或映射範本，請執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-resolver.html)命令。

   除了 `api-id` 參數之外，`create-resolver`命令中使用的參數會被`update-resolver`命令中的新值覆寫。

------

## 新增變動的解析程式
<a name="adding-a-resolver-for-mutations"></a>

下一個步驟是為您的 `Mutation` 類型建立解析程式。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**結構描述**。

1. 在**變動**類型下，選擇`addTodo`欄位旁的**連接**。

1. 在**建立解析程式**頁面上，選擇您在[連接資料來源指南中建立的資料來源](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)。

1. 在**設定映射範本**視窗中，您將需要修改請求範本，因為這是您要將新項目新增至 DynamoDB 的變動。請使用下列要求映射範本：

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

1. AWS AppSync 會自動將 `addTodo` 欄位中定義的引數從 GraphQL 結構描述轉換為 DynamoDB 操作。先前的範例使用 索引鍵將記錄存放在 DynamoDB 中`id`，該索引鍵會從變動引數傳遞為 `$ctx.args.id`。您傳遞的所有其他欄位都會使用 自動映射至 DynamoDB 屬性`$util.dynamodb.toMapValuesJson($ctx.args)`。

   在此解析程式中，使用下列的回應映射範本：

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

   AWS AppSync 也支援用於編輯解析程式的測試和偵錯工作流程。您可以使用模擬 `context` 物件，先查看範本轉換後的值，然後再叫用。或者，您可以在執行查詢時以互動方式檢視對資料來源的完整要求執行。如需詳細資訊，請參閱[測試和偵錯解析程式](test-debug-resolvers.md#aws-appsync-test-debug-resolvers)以及[監控和記錄](monitoring.md#aws-appsync-monitoring)。

1. 選擇**儲存解析程式**。

------
#### [ API ]

您也可以使用[建立第一個解析程式](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver)區段中的命令和本節中的參數詳細資訊，以 APIs 執行此操作。

------
#### [ CLI ]

您也可以使用[建立第一個解析程式](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver)區段中的命令和本節中的參數詳細資訊，在 CLI 中執行此操作。

------

此時，如果您未使用進階解析程式，您可以開始使用 GraphQL API，如[使用 API](using-your-api.md#aws-appsync-using-your-api) 中所述。

## 進階解析程式
<a name="advanced-resolvers"></a>

如果您遵循進階區段，並在[設計結構描述以執行分頁掃描中建置範例結構描述](designing-your-schema.md#aws-appsync-designing-your-schema)，請改用下列請求範本做為 `getTodos` 欄位：

```
{
    "version" : "2017-02-28",
    "operation" : "Scan",
    "limit": $util.defaultIfNull(${ctx.args.limit}, 20),
    "nextToken": $util.toJson($util.defaultIfNullOrBlank($ctx.args.nextToken, null))
}
```

對此分頁使用案例而言，回應映射不只是傳遞，因為其中必須包含*游標* (讓用戶端了解接下來從哪個頁面開始) 和結果集。映射範本如下所示：

```
{
    "todos": $util.toJson($context.result.items),
    "nextToken": $util.toJson($context.result.nextToken)
}
```

前述回應映射範本的欄位，應符合 `TodoConnection` 類型之中定義的欄位。

對於您擁有`Comments`資料表且正在解析`Todo`類型 （傳回 類型的`[Comment]`) 註解欄位的關係，您可以使用對第二個資料表執行查詢的映射範本。若要這樣做，您必須已經建立`Comments`資料表的資料來源，如[連接資料來源](attaching-a-data-source.md#aws-appsync-getting-started-build-a-schema-from-scratch)中所述。

**注意**  
我們針對第二個資料表使用查詢操作，僅供說明之用。您可以改為對 DynamoDB 使用其他操作。此外，您可以從其他資料來源提取資料，例如 AWS Lambda 或 Amazon OpenSearch Service，因為關係是由 GraphQL 結構描述控制。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**結構描述**。

1. 在**待辦事項**類型下，選擇`comments`欄位旁的**連接**。

1. 在**建立解析程式**頁面上，選擇您的**註解**資料表資料來源。快速入門指南中**註解**資料表的預設名稱為 `AppSyncCommentTable`，但可能會因您提供的名稱而有所不同。

1. 將下列程式碼片段新增至您的請求映射範本：

   ```
   {
       "version": "2017-02-28",
       "operation": "Query",
       "index": "todoid-index",
       "query": {
           "expression": "todoid = :todoid",
           "expressionValues": {
               ":todoid": {
                   "S": $util.toJson($context.source.id)
               }
           }
       }
   }
   ```

1. `context.source` 參照目前正在解析之欄位的父物件。在這個範例中，`source.id` 代表個別 `Todo` 物件，這個物件會在稍後用於查詢表達式。

   您可使用傳遞回應映射範本，如下所示：

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

1. 選擇**儲存解析程式**。

1. 最後，回到 主控台的**結構描述**頁面，將解析程式連接到 `addComment` 欄位，並指定`Comments`資料表的資料來源。在這種情況下，要求映射範本是簡單的 `PutItem`，其中具有註解為引數的特定 `todoid`，但您需要使用 `$utils.autoId()` 公用程式來為註解建立唯一的排序索引鍵，如下所示：

   ```
   {
       "version": "2017-02-28",
       "operation": "PutItem",
       "key": {
           "todoid": { "S": $util.toJson($context.arguments.todoid) },
           "commentid": { "S": "$util.autoId()" }
       },
       "attributeValues" : $util.dynamodb.toMapValuesJson($ctx.args)
   }
   ```

   使用傳遞回應範本，如下所示：

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

------
#### [ API ]

您也可以使用[建立第一個解析程式](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver)區段中的命令和本節中的參數詳細資訊，以 APIs 執行此操作。

------
#### [ CLI ]

您也可以使用[建立第一個解析程式](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html#create-your-first-resolver)區段中的命令和本節中的參數詳細資訊，在 CLI 中執行此操作。

------

# 使用直接 Lambda 解析程式 (VTL) 停用 VTL 映射範本
<a name="direct-lambda-reference"></a>

**注意**  
我們現在主要支援 APPSYNC\$1JS 執行期及其文件。請考慮[在此處](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html)使用 APPSYNC\$1JS 執行期及其指南。

使用直接 Lambda 解析程式時，您可以避免使用 VTL 映射範本 AWS Lambda 。 AWS AppSync 可以為您的 Lambda 函數提供預設承載，以及從 Lambda 函數對 GraphQL 類型的回應進行預設轉譯。您可以選擇提供請求範本、回應範本，或由 and AWS AppSync 處理。

若要進一步了解 AWS AppSync 提供的預設請求承載和回應轉譯，請參閱 [Direct Lambda 解析程式參考](resolver-mapping-template-reference-lambda.md#direct-lambda-resolvers)。如需設定 AWS Lambda 資料來源和設定 IAM 信任政策的詳細資訊，請參閱[連接資料來源](attaching-a-data-source.md)。

## 設定直接 Lambda 解析程式
<a name="direct-lambda-reference-resolvers"></a>

以下各節將說明如何連接 Lambda 資料來源，並將 Lambda 解析程式新增至您的欄位。

### 新增 Lambda 資料來源
<a name="direct-lambda-datasource"></a>

您必須先新增 Lambda 資料來源，才能啟用直接 Lambda 解析程式。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**資料來源**。

1. 選擇 **Create data source (建立資料來源)**。

   1. 針對**資料來源名稱**，輸入資料來源的名稱，例如 **myFunction**。

   1. 針對**資料來源類型**，選擇 **AWS Lambda 函數**。

   1. 針對**區域**，選擇適當的區域。

   1. 對於**函數 ARN**，從下拉式清單中選擇 Lambda 函數。您可以搜尋函數名稱，或手動輸入您要使用的函數 ARN。

   1. 建立新的 IAM 角色 （建議） 或選擇具有 IAM `lambda:invokeFunction` 許可的現有角色。現有角色需要信任政策，如[連接資料來源](attaching-a-data-source.md)一節所述。

      以下是 IAM 政策範例，其具有對資源執行操作所需的許可：

------
#### [ JSON ]

****  

      ```
      { 
           "Version":"2012-10-17",		 	 	  
           "Statement": [ 
               { 
                   "Effect": "Allow", 
                   "Action": [ "lambda:invokeFunction" ], 
                   "Resource": [ 
                       "arn:aws:lambda:us-west-2:123456789012:function:myFunction", 
                       "arn:aws:lambda:us-west-2:123456789012:function:myFunction:*" 
                   ] 
               } 
           ] 
       }
      ```

------

1. 選擇**建立**按鈕。

------
#### [ CLI ]

1. 執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-data-source.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-data-source.html)命令來建立資料來源物件。

   您需要為此特定命令輸入 4 個參數：

   1. 您 API `api-id`的 。

   1. 資料來源`name`的 。在主控台範例中，這是**資料來源名稱**。

   1. 資料來源`type`的 。在主控台範例中，這是 **AWS Lambda 函數**。

   1. `lambda-config`，這是主控台範例中的**函數 ARN**。
**注意**  
還有其他參數，例如 必須設定 `Region` ，但通常會預設為您的 CLI 組態值。

   範例命令可能如下所示：

   ```
   aws appsync create-data-source --api-id abcdefghijklmnopqrstuvwxyz --name myFunction --type AWS_LAMBDA --lambda-config lambdaFunctionArn=arn:aws:lambda:us-west-2:102847592837:function:appsync-lambda-example
   ```

   輸出會在 CLI 中傳回。範例如下：

   ```
   {
       "dataSource": {
           "dataSourceArn": "arn:aws:appsync:us-west-2:102847592837:apis/abcdefghijklmnopqrstuvwxyz/datasources/myFunction",
           "type": "AWS_LAMBDA",
           "name": "myFunction",
           "lambdaConfig": {
               "lambdaFunctionArn": "arn:aws:lambda:us-west-2:102847592837:function:appsync-lambda-example"
           }
       }
   }
   ```

1. 若要修改資料來源的屬性，請執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-data-source.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/update-data-source.html)命令。

   除了 `api-id` 參數之外，`create-data-source`命令中使用的參數將由`update-data-source`命令中的新值覆寫。

------

### 啟用直接 Lambda 解析程式
<a name="direct-lambda-enable-templates"></a>

建立 Lambda 資料來源並設定適當的 IAM 角色以允許 AWS AppSync 叫用函數後，您可以將其連結至解析程式或管道函數。

------
#### [ Console ]

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**結構描述**。

1. 在**解析程式**視窗中，選擇欄位或操作，然後選取**連接**按鈕。

1. 在**建立新的解析程式**頁面中，從下拉式清單中選擇 Lambda 函數。

1. 為了利用直接 Lambda 解析程式，請確認在**設定映射範本區段中已停用請求和回應映射範本**。

1. 選擇**儲存解析程式**按鈕。

------
#### [ CLI ]
+ 執行 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/appsync/create-resolver.html)命令來建立解析程式。

  您需要為此特定命令輸入 6 個參數：

  1. 您 API `api-id`的 。

  1. 結構描述中 `type-name` 類型的 。

  1. 結構描述中 欄位`field-name`的 。

  1. `data-source-name`或您的 Lambda 函數名稱。

  1. `request-mapping-template`，這是請求的內文。在主控台範例中，已停用：

     ```
     " "
     ```

  1. `response-mapping-template`，這是回應的內文。在主控台範例中，這也已停用：

     ```
     " "
     ```

  範例命令可能如下所示：

  ```
  aws appsync create-resolver --api-id abcdefghijklmnopqrstuvwxyz --type-name Subscription --field-name onCreateTodo --data-source-name LambdaTest --request-mapping-template " " --response-mapping-template " "
  ```

  輸出會在 CLI 中傳回。範例如下：

  ```
  {
      "resolver": {
          "resolverArn": "arn:aws:appsync:us-west-2:102847592837:apis/abcdefghijklmnopqrstuvwxyz/types/Subscription/resolvers/onCreateTodo",
          "typeName": "Subscription",
          "kind": "UNIT",
          "fieldName": "onCreateTodo",
          "dataSourceName": "LambdaTest"
      }
  }
  ```

------

當您停用映射範本時，會在 中發生幾個額外的行為 AWS AppSync：
+ 透過停用映射範本，您要向 發出訊號 AWS AppSync ，表示您接受 [Direct Lambda 解析程式參考](resolver-mapping-template-reference-lambda.md#direct-lambda-resolvers)中指定的預設資料轉譯。
+ 透過停用請求映射範本，您的 Lambda 資料來源將收到包含整個[內容](resolver-context-reference.md)物件的承載。
+ 透過停用回應映射範本，您的 Lambda 調用結果將根據請求映射範本的版本或請求映射範本是否也停用而翻譯。

# 測試和偵錯解析程式 in AWS AppSync (VTL)
<a name="test-debug-resolvers"></a>

**注意**  
我們現在主要支援 APPSYNC\$1JS 執行期及其文件。請考慮[在此處](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html)使用 APPSYNC\$1JS 執行期及其指南。

AWS AppSync 會對資料來源在 GraphQL 欄位上執行解析程式。如[解析程式映射範本概觀](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview)中所述，解析程式會使用範本語言與資料來源通訊。這可讓您自訂行為，並在與資料來源通訊前後套用邏輯和條件。如需撰寫解析程式的教學風格程式設計指南簡介，請參閱[解析程式映射範本程式設計指南](resolver-mapping-template-reference-programming-guide.md#aws-appsync-resolver-mapping-template-reference-programming-guide)。

為了協助開發人員寫入、測試和偵錯這些解析程式， AWS AppSync 主控台也提供工具來建立 GraphQL 請求和回應，並將模擬資料縮減至個別欄位解析程式。此外，您可以在 AWS AppSync 主控台中執行查詢、變動和訂閱，並從 Amazon CloudWatch 查看整個請求的詳細日誌串流。其中包括資料來源的結果。

## 使用模擬資料進行測試
<a name="testing-with-mock-data"></a>

叫用 GraphQL 解析程式時，會包含包含請求相關資訊的`context`物件。其中包括用戶端引數、身分資訊，以及父 GraphQL 欄位的資料。它還包含來自資料來源的結果，可用於回應範本。如需詳細資訊來了解此項架構，以及程式設計時可用的各種協助公用程式，請參閱[解析程式映射範本內容參考](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference)。

寫入或編輯解析程式時，您可以將*模擬*或*測試內容*物件傳遞至主控台編輯器。這可讓您在沒有實際依據資料來源執行的情況下，了解這兩者如何請求及回應範本評估。例如您可傳送測試 `firstname: Shaggy` 引數，了解該引數在範本程式碼之中使用 `$ctx.args.firstname` 時如何進行評估。您也可以測試任何公用程式協助程式的評估，例如 `$util.autoId()` 或 `util.time.nowISO8601()`。

### 測試解析程式
<a name="test-a-resolver"></a>

此範例將使用 AWS AppSync 主控台來測試解析程式。

1. 登入 AWS 管理主控台 並開啟 [AppSync 主控台](https://console.aws.amazon.com/appsync/)。

   1. 在 **APIs儀表板**中，選擇您的 GraphQL API。

   1. 在**側邊欄中**，選擇**結構描述**。

1. 如果您尚未這麼做，請在 類型下和 欄位旁，選擇**連接**以新增您的解析程式。

   如需如何建置完整解析程式的詳細資訊，請參閱[設定解析程式](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers.html)。

   否則，請選取已在 欄位中的解析程式。

1. 在**編輯解析程式**頁面頂端，選擇**選取測試內容**，然後選擇**建立新內容**。

1. 選取範例內容物件，或在下方的**執行內容**視窗中手動填入 JSON。

1. 在**文字內容名稱**中輸入 。

1. 選擇 **Save (儲存)** 按鈕。

1. 在**編輯解析程式**頁面頂端，選擇**執行測試**。

如需更實際的範例，假設您有一個應用程式存放的 GraphQL 類型`Dog`，該類型使用物件的自動 ID 產生，並將它們存放在 Amazon DynamoDB 中。您也希望寫入 GraphQL 變動引數的值，並且只讓特定使用者看見回應。結構描述看起來類似如下：

```
type Dog {
  breed: String
  color: String
}

type Mutation {
  addDog(firstname: String, age: Int): Dog
}
```

當您為`addDog`變動新增解析程式時，您可以填入內容物件，如下列範例所示。下列引數來自 `name` 及 `age`，以及將 `username` 填入 `identity` 物件之中的用戶端：

```
{
    "arguments" : {
        "firstname": "Shaggy",
        "age": 4
    },
    "source" : {},
    "result" : {
        "breed" : "Miniature Schnauzer",
        "color" : "black_grey"
    },
    "identity": {
        "sub" : "uuid",
        "issuer" : " https://cognito-idp.{region}.amazonaws.com/{userPoolId}",
        "username" : "Nadia",
        "claims" : { },
        "sourceIp" :[  "x.x.x.x" ],
        "defaultAuthStrategy" : "ALLOW"
    }
}
```

您可利用下列要求及回應映射範本對此進行測試：

 **請求範本** 

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

 **回應範本** 

```
#if ($context.identity.username == "Nadia")
  $util.toJson($ctx.result)
#else
  $util.unauthorized()
#end
```

經過評估的範本擁有測試內容物件的資料，以及 `$util.autoId()` 產生的值。此外，若您將 `username` 變更為 `Nadia` 以外的值，將不會傳回結果，因為授權檢查將會失敗。如需精細存取控制的詳細資訊，請參閱[授權使用案例](security-authorization-use-cases.md#aws-appsync-security-authorization-use-cases)。

### 使用 AWS AppSync 的 APIs測試映射範本
<a name="testing-with-appsync-api"></a>

您可以使用 `EvaluateMappingTemplate` API 命令，以模擬資料遠端測試映射範本。若要開始使用 命令，請確定您已將 `appsync:evaluateMappingTemplate`許可新增至政策。例如：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "appsync:evaluateMappingTemplate",
            "Resource": "arn:aws:appsync:us-east-1:111122223333:*"
        }
    ]
}
```

------

您可以使用 [AWS CLI](https://aws.amazon.com/cli/)或 [AWS SDKs](https://aws.amazon.com/tools/) 來利用 命令。例如，從上一節取得`Dog`結構描述及其請求/回應映射範本。在本機工作站上使用 CLI，將請求範本儲存到名為 的檔案`request.vtl`，然後將`context`物件儲存到名為 的檔案`context.json`。從您的 shell 執行下列命令：

```
aws appsync evaluate-mapping-template --template file://request.vtl --context file://context.json
```

該命令會傳回下列回應：

```
{
  "evaluationResult": "{\n    \"version\" : \"2017-02-28\",\n    \"operation\" : \"PutItem\",\n    \"key\" : {\n        \"id\" : { \"S\" : \"afcb4c85-49f8-40de-8f2b-248949176456\" }\n    },\n    \"attributeValues\" : {\"firstname\":{\"S\":\"Shaggy\"},\"age\":{\"N\":4}}\n}\n"
}
```

`evaluationResult` 包含使用提供的 測試您提供的範本的結果`context`。您也可以使用 AWS SDKs測試範本。以下是使用適用於 JavaScript V2 的 AWS SDK 的範例：

```
const AWS = require('aws-sdk')
const client = new AWS.AppSync({ region: 'us-east-2' })

const template = fs.readFileSync('./request.vtl', 'utf8')
const context = fs.readFileSync('./context.json', 'utf8')

client
  .evaluateMappingTemplate({ template, context })
  .promise()
  .then((data) => console.log(data))
```

使用 SDK，您可以輕鬆整合來自您最愛測試套件的測試，以驗證範本的行為。我們建議您使用 [Jest 測試架構](https://jestjs.io/)建立測試，但任何測試套件都可以運作。下列程式碼片段顯示假設性驗證執行。請注意，我們預期評估回應是有效的 JSON，因此我們使用 從字串回應`JSON.parse`擷取 JSON：

```
const AWS = require('aws-sdk')
const fs = require('fs')
const client = new AWS.AppSync({ region: 'us-east-2' })

test('request correctly calls DynamoDB', async () => {
  const template = fs.readFileSync('./request.vtl', 'utf8')
  const context = fs.readFileSync('./context.json', 'utf8')
  const contextJSON = JSON.parse(context)
  
  const response = await client.evaluateMappingTemplate({ template, context }).promise()
  const result = JSON.parse(response.evaluationResult)
  
  expect(result.key.id.S).toBeDefined()
  expect(result.attributeValues.firstname.S).toEqual(contextJSON.arguments.firstname)
})
```

 這會產生下列結果：

```
Ran all test suites.
> jest

PASS ./index.test.js
✓ request correctly calls DynamoDB (543 ms)

Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.511 s, estimated 2 s
```

## 偵錯即時查詢
<a name="debugging-a-live-query"></a>

end-to-end測試和記錄無法用來偵錯生產應用程式。 AWS AppSync 可讓您使用 Amazon CloudWatch 記錄錯誤和完整請求詳細資訊。此外，您可以使用 AWS AppSync 主控台來測試 GraphQL 查詢、變動和訂閱，以及將每個請求的即時串流日誌資料傳回查詢編輯器以進行即時偵錯。針對訂閱，日誌會顯示連線時間資訊。

若要執行此操作，您需要事先啟用 Amazon CloudWatch logs，如[監控和記錄](monitoring.md#aws-appsync-monitoring)中所述。接著，在 AWS AppSync 主控台中，選擇**查詢**索引標籤，然後輸入有效的 GraphQL 查詢。在右下角區段中，按一下並拖曳**日誌**視窗以開啟日誌檢視。在頁面頂端，選擇執行箭頭圖示來執行您的 GraphQL 查詢。幾分鐘後，操作的完整請求及回應日誌，將串流至此區段，然後您可在主控台中檢視。

# 設定和使用管道解析程式 in AWS AppSync (VTL)
<a name="pipeline-resolvers"></a>

**注意**  
我們現在主要支援 APPSYNC\$1JS 執行期及其文件。請考慮[在此處](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html)使用 APPSYNC\$1JS 執行期及其指南。

AWS AppSync 會在 GraphQL 欄位上執行解析程式。在某些情況下，應用程式需要執行多個操作，才能解析單一 GraphQL 欄位。透過管道解析程式，開發人員現在可以編寫稱為 Functions 的操作，並依序執行這些操作。在像是以需要先執行授權檢查才能擷取欄位資料的情況中，就很適合使用管道解析程式。

管道解析程式包含 **Before** 映射範本和 **After** 映射範本，以及一份函數清單。每個函數都有一個**請求**和**回應**映射範本，它會針對資料來源執行。由於管道解析程式是將執行委派到一份函數清單，所以不會連結到任何資料來源。單位解析程式和函數是對資料來源執行操作的基礎。如需詳細資訊，請參閱[解析程式映射範本概觀](resolver-mapping-template-reference-overview.md#aws-appsync-resolver-mapping-template-reference-overview)。

## 步驟 1：建立管道解析程式
<a name="create-a-pipeline-resolver"></a>

在 AWS AppSync 主控台中，前往**結構描述**頁面。

儲存下列結構描述：

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

type Mutation {
    signUp(input: Signup): User
}

type Query {
    getUser(id: ID!): User
}

input Signup {
    username: String!
    email: String!
}

type User {
    id: ID!
    username: String
    email: AWSEmail
}
```

我們將將管道解析程式連接到 **Mutation** 類型的 **signUp** 欄位。在右側的**變動**類型中，選擇`signUp`變動欄位旁的**連接**。在建立解析程式頁面上，按一下**動作**，然後按一下**更新執行時間**。選擇 `Pipeline Resolver`，然後選擇 `VTL`，然後選擇**更新**。頁面現在應會顯示三個區段：**映射前範本**文字區域、**函數**區段，以及**映射後範本**文字區域。

我們的管道解析程式會註冊使用者，此註冊的第一步是驗證電子郵件地址輸入，然後在系統中儲存此位使用者。我們將在 **validateEmail** 函數中封裝該電子郵件驗證，並在 **saveUser** 函數中封裝使用者儲存步驟。**validateEmail** 函數會先執行，而當電子郵件驗證有效時，**saveUser** 函數就會接著執行。

執行流程將如下所示：

1. Mutation.signUp 解析程式要求映射範本

1. validateEmail 函數

1. saveUser 函數

1. Mutation.signUp 解析程式回應映射範本

由於我們可能會在 API 上的其他解析程式中重複使用 **validateEmail** 函數，因此我們希望避免存取 ，`$ctx.args`因為這些函數會從一個 GraphQL 欄位變更為另一個欄位。反之，我們可以使用 `$ctx.stash` 來存放 `signUp(input: Signup)` 輸入欄位引數所傳遞的電子郵件屬性。

映射範本**之前**：

```
## store email input field into a generic email key
$util.qr($ctx.stash.put("email", $ctx.args.input.email))
{}
```

主控台提供預設的 **AFTER** 映射範本，我們將使用：

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

選擇**建立**或**儲存**以更新解析程式。

## 步驟 2：建立 函數
<a name="create-a-function"></a>

在管道解析程式頁面的**函數**區段中，按一下**新增函數**，然後按一下**建立新函數**。您也可以在不經過解析程式頁面的情況下建立函數；若要這樣做，請在 AWS AppSync 主控台中前往**函數**頁面。選擇 **Create function (建立函數)** 按鈕。讓我們來建立可檢查電子郵件是否有效且來源是特定網域的函數。如果電子郵件無效，則該函數會引發錯誤。否則，它會轉送任何獲予的任何輸入。

在新函數頁面上，選擇**動作**，然後選擇**更新執行時間**。選擇 `VTL`，然後選擇**更新**。請確定您已建立 **NONE** 類型的資料來源。在資料來源**名稱清單中選擇此資料來源**。在**函數名稱**中輸入 `validateEmail`。在**函數程式碼**區域中，使用此程式碼片段覆寫所有項目：

```
#set($valid = $util.matches("^[a-zA-Z0-9_.+-]+@(?:(?:[a-zA-Z0-9-]+\.)?[a-zA-Z]+\.)?(myvaliddomain)\.com", $ctx.stash.email))
#if (!$valid)
    $util.error("$ctx.stash.email is not a valid email.")
#end
{
    "payload": { "email": $util.toJson(${ctx.stash.email}) }
}
```

將此貼到回應映射範本中：

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

檢閱您的變更，然後選擇**建立**。我們已建立我們 **validateEmail** 函數。重複這些步驟，使用下列請求和回應映射範本建立 **saveUser** 函數 （為了簡單起見，我們使用 **NONE** 資料來源，並在函數執行後假設使用者已儲存在系統中。)：

要求映射範本：

```
## $ctx.prev.result contains the signup input values. We could have also
## used $ctx.args.input.
{
    "payload": $util.toJson($ctx.prev.result)
}
```

回應映射範本：

```
## an id is required so let's add a unique random identifier to the output
$util.qr($ctx.result.put("id", $util.autoId()))
$util.toJson($ctx.result)
```

我們剛建立了 **saveUser** 函數。

## 步驟 3：將函數新增至管道解析程式
<a name="adding-a-function-to-a-pipeline-resolver"></a>

我們的函數應該會自動新增至我們剛建立的管道解析程式。如果不是這種情況，或者您透過函數頁面建立**函數**，您可以在解析程式頁面上按一下**新增函數**來連接它們。將 **validateEmail** 和 **saveUser** 函數新增至解析程式。**validateEmail** 函數應該放在 **saveUser** 函數之前。當您新增更多函數時，您可以使用**上下****移動**選項來重組函數的執行順序。檢閱您的變更，然後選擇**儲存**。

## 步驟 4：執行查詢
<a name="executing-a-query"></a>

在 AWS AppSync 主控台中，前往**查詢**頁面。在瀏覽器中，請確定您使用的是變動。如果不是，請在下拉式清單`Mutation`中選擇 ，然後選擇 `+`。輸入下列查詢：

```
mutation {
  signUp(input: {
    email: "nadia@myvaliddomain.com"
    username: "nadia"
  }) {
    id
    email
  }
}
```

這應該會傳回如下內容：

```
{
  "data": {
    "signUp": {
      "id": "256b6cc2-4694-46f4-a55e-8cb14cc5d7fc",
      "email": "nadia@myvaliddomain.com"
    }
  }
}
```

我們已使用管道解析程式成功註冊我們的使用者，並完成輸入電子郵件的驗證。若要取得更多著重管道解析程式的全面教學課程，您可以移至[教學課程：管道解析程式](tutorial-pipeline-resolvers.md#aws-appsync-tutorial-pipeline-resolvers) 

# 搭配 AWS CDK 使用 AWS AppSync API
<a name="using-your-api"></a>

**提示**  
在使用 CDK 之前，我們建議您檢閱 CDK 的[官方文件](https://docs.aws.amazon.com/cdk/v2/guide/getting_started.html)以及 CDK AWS AppSync參考。 [https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_appsync-readme.html)  
我們也建議確保您的 [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) 和 [NPM](https://docs.npmjs.com/) 安裝可在您的系統上運作。

在本節中，我們將建立簡單的 CDK 應用程式，可從 DynamoDB 資料表新增和擷取項目。這是使用[設計結構描述](https://docs.aws.amazon.com/appsync/latest/devguide/designing-your-schema.html)、[連接資料來源](https://docs.aws.amazon.com/appsync/latest/devguide/attaching-a-data-source.html)和[設定解析程式 (JavaScript)](https://docs.aws.amazon.com/appsync/latest/devguide/configuring-resolvers-js.html) 區段中的一些程式碼的快速入門範例。

## 設定 CDK 專案
<a name="Setting-up-a-cdk-project"></a>

**警告**  
視您的環境而定，這些步驟可能不完全準確。我們假設您的系統已安裝必要的公用程式、與服務的界面方式 AWS ，以及適當的組態。

第一步是安裝 AWS CDK。在 CLI 中，您可以輸入下列命令：

```
npm install -g aws-cdk
```

接著，您需要建立專案目錄，然後導覽至它。建立和導覽至目錄的一組命令範例如下：

```
mkdir example-cdk-app
cd example-cdk-app
```

接著，您需要建立應用程式。我們的服務主要使用 TypeScript。在您的專案目錄中，輸入下列命令：

```
cdk init app --language typescript
```

當您執行此操作時，將會安裝 CDK 應用程式及其初始化檔案：

![\[Terminal output showing Git repository initialization and npm install completion.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-init-app-example.png)


您的專案結構可能如下所示：

![\[Project directory structure showing folders and files for an example CDK app.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-init-directories.png)


您會注意到我們有幾個重要的目錄：
+ `bin`：初始 bin 檔案將建立應用程式。我們不會在本指南中碰觸到此項目。
+ `lib`：lib 目錄包含您的堆疊檔案。您可以將堆疊檔案視為個別的執行單位。建構將位於我們的堆疊檔案內。基本上，這些是服務的資源，會在應用程式部署 CloudFormation 時在其中啟動。這就是我們大部分編碼都會發生的地方。
+ `node_modules`：此目錄是由 NPM 建立，並包含您使用 `npm`命令安裝的所有套件相依性。

我們的初始堆疊檔案可能包含如下內容：

```
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
// import * as sqs from 'aws-cdk-lib/aws-sqs';

export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // The code that defines your stack goes here

    // example resource
    // const queue = new sqs.Queue(this, 'ExampleCdkAppQueue', {
    //   visibilityTimeout: cdk.Duration.seconds(300)
    // });
  }
}
```

這是在我們的應用程式中建立堆疊的樣板程式碼。我們在此範例中的大部分程式碼都會進入此類別的範圍內。

若要驗證您的堆疊檔案是否在應用程式中，請在應用程式的 目錄中，在終端機中執行下列命令：

```
cdk ls
```

應該會出現堆疊的清單。如果沒有，則您可能需要再次執行這些步驟，或查看官方文件以取得協助。

如果您想要在部署之前建置程式碼變更，您可以隨時在終端機中執行下列命令：

```
npm run build
```

此外，若要在部署之前查看變更：

```
cdk diff
```

將程式碼新增至堆疊檔案之前，我們會執行引導。引導允許我們在應用程式部署之前佈建 CDK 的資源。如需此程序的詳細資訊，請參閱[此處](https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html)。若要建立引導，命令為：

```
cdk bootstrap aws://ACCOUNT-NUMBER/REGION
```

**提示**  
此步驟需要您帳戶中的數個 IAM 許可。如果您沒有引導，您的引導將被拒絕。如果發生這種情況，您可能需要刪除由引導造成的不完整資源，例如它產生的 S3 儲存貯體。

Bootstrap 將啟動數個資源。最終訊息會如下所示：

![\[Terminal output showing successful bootstrapping of an AWS environment.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-init-bootstrap-final.png)


每個區域每個帳戶會執行一次此操作，因此您不需要經常執行此操作。引導的主要資源是 CloudFormation 堆疊和 Amazon S3 儲存貯體。

Amazon S3 儲存貯體用於存放授予執行部署所需許可的檔案和 IAM 角色。所需的資源是在 CloudFormation 堆疊中定義，稱為引導堆疊，通常命名為 `CDKToolkit`。與任何 CloudFormation 堆疊一樣，它在部署之後會出現在 CloudFormation 主控台中：

![\[CDKToolkit stack with CREATE_COMPLETE status in CloudFormation console.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-init-bootstrap-cfn-console.png)


您可以針對儲存貯體說出相同的 ：

![\[S3 bucket details showing name, region, access settings, and creation date.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-init-bootstrap-bucket-console.png)


若要匯入堆疊檔案中所需的服務，我們可以使用下列命令：

```
npm install aws-cdk-lib # V2 command
```

**提示**  
如果 V2 發生問題，您可以使用 V1 命令安裝個別程式庫：  

```
npm install @aws-cdk/aws-appsync @aws-cdk/aws-dynamodb
```
我們不建議這麼做，因為 V1 已棄用。

## 實作 CDK 專案 - 結構描述
<a name="implementing-a-cdk-project-schema"></a>

我們現在可以開始實作程式碼。首先，我們必須建立結構描述。您可以直接在應用程式中建立`.graphql`檔案：

```
mkdir schema
touch schema.graphql
```

在我們的範例中，我們包含了一個名為 的頂層目錄，`schema`其中包含我們的 `schema.graphql`：

![\[File structure showing a schema folder containing schema.graphql file.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-schema-directory.png)


在我們的結構描述中，讓我們包含一個簡單的範例：

```
input CreatePostInput {
    title: String
    content: String
}

type Post {
    id: ID!
    title: String
    content: String
}

type Mutation {
    createPost(input: CreatePostInput!): Post
}

type Query {
    getPost: [Post]
}
```

回到堆疊檔案，我們需要確定已定義下列匯入指令：

```
import * as cdk from 'aws-cdk-lib';
import * as appsync from 'aws-cdk-lib/aws-appsync';
import * as dynamodb from 'aws-cdk-lib/aws-dynamodb';
import { Construct } from 'constructs';
```

在 類別中，我們將新增程式碼來製作 GraphQL API，並將其連接到我們的`schema.graphql`檔案：

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    // makes a GraphQL API
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });
  }
}
```

我們也會新增一些程式碼來列印 GraphQL URL、API 金鑰和區域：

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    
    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

此時，我們將再次使用部署應用程式：

```
cdk deploy
```

這是結果：

![\[Deployment output showing ExampleCdkAppStack details, including GraphQL API URL and stack region.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-schema.png)


顯示我們的範例成功，但讓我們檢查 AWS AppSync 主控台以確認：

![\[GraphQL interface showing successful API request with response data displayed.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-schema-result-1.png)


我們的 API 似乎已建立。現在，我們將檢查連接到 API 的結構描述：

![\[GraphQL schema defining CreatePostInput, Post type, Mutation, and Query operations.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-schema-result-2.png)


這似乎符合我們的結構描述程式碼，因此成功。從中繼資料觀點確認這一點的另一個方法是查看 CloudFormation 堆疊：

![\[CloudFormation stack showing ExampleCdkAppStack update complete and CDKToolkit creation complete.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-schema-result-3.png)


當我們部署 CDK 應用程式時，它會逐步 CloudFormation 啟動引導等資源。我們應用程式內的每個堆疊都會以 1：1 與 CloudFormation 堆疊映射。如果您返回堆疊程式碼，堆疊名稱會從類別名稱 中擷取`ExampleCdkAppStack`。您可以在 GraphQL API 建構中查看其建立的資源，這也符合我們的命名慣例：

![\[Expanded view of post-apis resource showing Schema, DefaultApiKey, and CDKMetadata.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-schema-result-4.png)


## 實作 CDK 專案 - 資料來源
<a name="implementing-a-cdk-project-data-source"></a>

接下來，我們需要新增資料來源。我們的範例將使用 DynamoDB 資料表。在堆疊類別中，我們會新增一些程式碼來建立新的資料表：

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    //creates a DDB table
    const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
      partitionKey: {
        name: 'id',
        type: dynamodb.AttributeType.STRING,
      },
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

此時，讓我們再次部署：

```
cdk deploy
```

我們應該檢查 DynamoDB 主控台是否有新的資料表：

![\[DynamoDB console showing ExampleCdkAppStack-poststable as Active with Provisioned capacity.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-ddb-result-1.png)


我們的堆疊名稱正確，且資料表名稱符合我們的程式碼。如果我們再次檢查 CloudFormation 堆疊，現在將會看到新的資料表：

![\[Expanded view of a logical ID in CloudFormation showing post-apis, posts-table, and CDKMetadata.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-ddb-result-2.png)


## 實作 CDK 專案 - Resolver
<a name="implementing-a-cdk-project-resolver"></a>

此範例將使用兩個解析程式：一個用於查詢資料表，另一個用於新增資料表。由於我們使用管道解析程式，因此我們需要宣告兩個管道解析程式，每個管道解析程式各有一個 函數。在查詢中，我們將新增下列程式碼：

```
export class ExampleCdkAppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Makes a GraphQL API construct
    const api = new appsync.GraphqlApi(this, 'post-apis', {
      name: 'api-to-process-posts',
      schema: appsync.SchemaFile.fromAsset('schema/schema.graphql'),
    });

    //creates a DDB table
    const add_ddb_table = new dynamodb.Table(this, 'posts-table', {
      partitionKey: {
        name: 'id',
        type: dynamodb.AttributeType.STRING,
      },
    });

    // Creates a function for query
    const add_func = new appsync.AppsyncFunction(this, 'func-get-post', {
      name: 'get_posts_func_1',
      api,
      dataSource: api.addDynamoDbDataSource('table-for-posts', add_ddb_table),
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return { operation: 'Scan' };
          }

          export function response(ctx) {
          return ctx.result.items;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
    });

    // Creates a function for mutation
    const add_func_2 = new appsync.AppsyncFunction(this, 'func-add-post', {
      name: 'add_posts_func_1',
      api,
      dataSource: api.addDynamoDbDataSource('table-for-posts-2', add_ddb_table),
      code: appsync.Code.fromInline(`
          export function request(ctx) {
            return {
            operation: 'PutItem',
            key: util.dynamodb.toMapValues({id: util.autoId()}),
            attributeValues: util.dynamodb.toMapValues(ctx.args.input),
            };
          }

          export function response(ctx) {
            return ctx.result;
          }
      `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
    });

    // Adds a pipeline resolver with the get function
    new appsync.Resolver(this, 'pipeline-resolver-get-posts', {
      api,
      typeName: 'Query',
      fieldName: 'getPost',
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return {};
          }

          export function response(ctx) {
          return ctx.prev.result;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
      pipelineConfig: [add_func],
    });

    // Adds a pipeline resolver with the create function
    new appsync.Resolver(this, 'pipeline-resolver-create-posts', {
      api,
      typeName: 'Mutation',
      fieldName: 'createPost',
      code: appsync.Code.fromInline(`
          export function request(ctx) {
          return {};
          }

          export function response(ctx) {
          return ctx.prev.result;
          }
  `),
      runtime: appsync.FunctionRuntime.JS_1_0_0,
      pipelineConfig: [add_func_2],
    });

    // Prints out URL
    new cdk.CfnOutput(this, "GraphQLAPIURL", {
      value: api.graphqlUrl
    });

    // Prints out the AppSync GraphQL API key to the terminal
    new cdk.CfnOutput(this, "GraphQLAPIKey", {
      value: api.apiKey || ''
    });

    // Prints out the stack region to the terminal
    new cdk.CfnOutput(this, "Stack Region", {
      value: this.region
    });
  }
}
```

在此程式碼片段中，我們新增了名為 的管道解析程式，`pipeline-resolver-create-posts`並`func-add-post`附加了名為 的函數。這是將`Posts`新增至資料表的程式碼。另一個管道解析程式使用名為 `pipeline-resolver-get-posts`的函數呼叫`func-get-post`，該函數會擷取`Posts`新增至資料表的 。

我們將部署此項目以將其新增至 AWS AppSync 服務：

```
cdk deploy
```

讓我們檢查 AWS AppSync 主控台，看看它們是否已連接到我們的 GraphQL API：

![\[GraphQL API schema showing mutation and query fields with Pipeline resolvers.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-1.png)


它看起來是正確的。在程式碼中，這兩個解析程式都連接到我們製作的 GraphQL API （由解析程式和函數中存在的 props `api` 值表示）。在 GraphQL API 中，我們連接解析程式的欄位也在 props 中指定 （由每個解析程式中的 `typename`和 `fieldname` props 定義）。

讓我們看看解析程式的內容從 開始是否正確`pipeline-resolver-get-posts`：

![\[Code snippet showing request and response functions in a resolver, with an arrow pointing to them.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-2.png)


前後處理常式符合我們的`code`道具值。我們也可以看到名為 的函數`add_posts_func_1`，其符合我們在解析程式中附加的函數名稱。

讓我們看看該函數的程式碼內容：

![\[Function code showing request and response methods for a PutItem operation.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-3.png)


這符合`add_posts_func_1`函數的`code`道具。我們的查詢已成功上傳，因此我們檢查查詢：

![\[Resolver code with request and response functions, and a get_posts_func_1 function listed below.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-4.png)


這些也符合程式碼。如果我們查看 `get_posts_func_1`：

![\[Code snippet showing two exported functions: request returning 'Scan' operation and response returning items.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-5.png)


一切似乎都就位。為了從中繼資料的角度確認這一點，我們可以再次檢查 中的 CloudFormation 堆疊：

![\[List of logical IDs for AWS resources including API, table, functions, and pipelines.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-deploy-resolver-result-6.png)


現在，我們需要執行一些請求來測試此程式碼。

## 實作 CDK 專案 - 請求
<a name="implementing-a-cdk-project-requests"></a>

為了在 AWS AppSync 主控台測試我們的應用程式，我們提出了一個查詢和一個變動：

![\[GraphQL code snippet showing a query to get post details and a mutation to create a post.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-request-1.png)


`MyMutation` 包含具有引數 `1970-01-01T12:30:00.000Z`和 `createPost`的操作`first post`。它會傳回我們傳入`title`的 `date`和 ，以及自動產生的`id`值。執行變動會產生結果：

```
{
  "data": {
    "createPost": {
      "date": "1970-01-01T12:30:00.000Z",
      "id": "4dc1c2dd-0aa3-4055-9eca-7c140062ada2",
      "title": "first post"
    }
  }
}
```

如果我們快速檢查 DynamoDB 資料表，我們可以在掃描時在資料表中看到我們的項目：

![\[DynamoDB table entry showing id, date, and title fields for a single item.\]](http://docs.aws.amazon.com/zh_tw/appsync/latest/devguide/images/cdk-code-request-2.png)


返回 AWS AppSync 主控台，如果我們執行查詢來擷取此 `Post`，我們會取得下列結果：

```
{
  "data": {
    "getPost": [
      {
        "id": "9f62c4dd-49d5-48d5-b835-143284c72fe0",
        "date": "1970-01-01T12:30:00.000Z",
        "title": "first post"
      }
    ]
  }
}
```