

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

# 使用 DynamoDB JavaScript 解析程式建立簡單的貼文應用程式
<a name="tutorial-dynamodb-resolvers-js"></a>

在本教學課程中，您將 Amazon DynamoDB 資料表匯入 AWS AppSync ，並使用 JavaScript 管道解析程式來連接它們，以建置功能完整的 GraphQL API，供您在自己的應用程式中使用。

您將使用 AWS AppSync 主控台來佈建 Amazon DynamoDB 資源、建立解析程式，並將它們連接到您的資料來源。您也可以透過 GraphQL 陳述式讀取和寫入 Amazon DynamoDB 資料庫，並訂閱即時資料。

您必須完成特定步驟，才能將 GraphQL 陳述式翻譯為 Amazon DynamoDB 操作，以及將回應翻譯回 GraphQL。本教學課程概述透過幾個真實世界案例和資料存取模式的組態程序。

## 建立 GraphQL API
<a name="create-graphql-api"></a>

**在 中建立 GraphQL API AWS AppSync**

1. 開啟 AppSync 主控台，然後選擇**建立 API**。

1. 選取**從頭開始設計**，然後選擇**下一步**。

1. 為您的 API 命名`PostTutorialAPI`，然後選擇**下一步**。跳到檢閱頁面，同時將其餘選項設定為其預設值，然後選擇 `Create`。

 AWS AppSync 主控台會為您建立新的 GraphQL API。透過停用，它會使用 API 金鑰身分驗證模式。您可以使用主控台來設定其他 GraphQL API 和對其執行查詢，以進行此教學的其他部分。

## 定義基本文章 API
<a name="define-post-api"></a>

現在您已擁有 GraphQL API，您可以設定基本結構描述，以允許基本建立、擷取和刪除文章資料。

**將資料新增至您的結構描述**

1. 在您的 API 中，選擇**結構描述**索引標籤。

1. 我們將建立結構描述，定義 `Post`類型和 操作`addPost`來新增和取得`Post`物件。在**結構描述**窗格中，使用下列程式碼取代內容：

   ```
   schema {
       query: Query
       mutation: Mutation
   }
   
   type Query {
       getPost(id: ID): Post
   }
   
   type Mutation {
       addPost(
           id: ID!
           author: String!
           title: String!
           content: String!
           url: String!
       ): Post!
   }
   
   type Post {
       id: ID!
       author: String
       title: String
       content: String
       url: String
       ups: Int!
       downs: Int!
       version: Int!
   }
   ```

1. 選擇 **Save Schema (儲存結構描述)**。

## 設定 Amazon DynamoDB 資料表
<a name="configure-dynamodb"></a>

 AWS AppSync 主控台可協助佈建所需的 AWS 資源，以將您自己的資源存放在 Amazon DynamoDB 資料表中。在此步驟中，您將建立 Amazon DynamoDB 資料表來存放您的文章。您也將設定[次要索引](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html)，以供我們稍後使用。

**建立 Amazon DynamoDB 資料表**

1. 在**結構描述**頁面上，選擇**建立資源**。

1. 選擇**使用現有類型**，然後選擇`Post`類型。

1. 在**其他索引**區段中，選擇**新增索引**。

1. 為索引命名 `author-index`。

1. 將 `Primary key` 設定為 `author`，將 `Sort`金鑰設定為 `None`。

1. 停用 **自動產生 GraphQL**。在此範例中，我們將自行建立解析程式。

1. 選擇**建立**。

您現在有名為 的新資料來源`PostTable`，您可以透過前往側邊標籤中的**資料來源**來查看。您將使用此資料來源將查詢和變動連結至 Amazon DynamoDB 資料表。

## 設定 addPost 解析程式 (Amazon DynamoDB PutItem)
<a name="configure-addpost"></a>

現在 AWS AppSync ，您知道 Amazon DynamoDB 資料表，您可以透過定義解析程式將其連結至個別查詢和變動。您建立的第一個解析程式是使用 JavaScript 的`addPost`管道解析程式，可讓您在 Amazon DynamoDB 資料表中建立文章。管道解析程式具有下列元件：
+ 在 GraphQL 結構描述中要附加解析程式的位置。在這種情況下，您會對 `createPost` 類型上的 `Mutation` 欄位設定解析程式。當發起人呼叫變動 時，將會叫用此解析程式`{ addPost(...){...} }`。
+ 用於此解析程式的資料來源。在此情況下，您想要使用先前定義的 DynamoDB 資料來源，因此您可以將項目新增至 `post-table-for-tutorial` DynamoDB 資料表。
+ 請求處理常式。請求處理常式是一種函數，可處理來自發起人的傳入請求，並將其轉換為指示 AWS AppSync ，讓 對 DynamoDB 執行。
+ 回應處理常式。回應處理常式的任務是處理來自 DynamoDB 的回應，並將其翻譯回 GraphQL 預期的內容。如果 DynamoDB 中的資料形狀與 GraphQL 中的 `Post` 類型不同，此功能會很有用，但如果他們的形狀一樣，您只需傳遞資料。

**設定您的解析程式**

1. 在您的 API 中，選擇**結構描述**索引標籤。

1. 在**解析程式**窗格中，尋找 `Mutation`類型下的 `addPost` 欄位，然後選擇**連接**。

1. 選擇您的資料來源，然後選擇**建立**。

1. 在您的程式碼編輯器中，使用此程式碼片段取代程式碼：

   ```
   import { util } from '@aws-appsync/utils'
   import * as ddb from '@aws-appsync/utils/dynamodb'
   
   export function request(ctx) {
   	const item = { ...ctx.arguments, ups: 1, downs: 0, version: 1 }
   	const key = { id: ctx.args.id ?? util.autoId() }
   	return ddb.put({ key, item })
   }
   
   export function response(ctx) {
   	return ctx.result
   }
   ```

1. 選擇**儲存**。

**注意**  
在此程式碼中，您可以使用 DynamoDB 模組 utils，讓您輕鬆地建立 DynamoDB 請求。

AWS AppSync 隨附名為 的自動 ID 產生公用程式`util.autoId()`，用於產生新文章的 ID。如果您未指定 ID，則公用程式會自動為您產生 ID。

```
const key = { id: ctx.args.id ?? util.autoId() }
```

如需 JavaScript 可用公用程式的詳細資訊，請參閱[解析程式和函數的 JavaScript 執行期功能](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html)。

### 呼叫 API 以新增文章
<a name="call-api-addpost"></a>

現在已設定解析程式， AWS AppSync 可以將傳入`addPost`的變動轉譯為 Amazon DynamoDB `PutItem`操作。您現在可以執行變動以將項目放置到資料表中。

**執行 操作**

1. 在您的 API 中，選擇**查詢**索引標籤。

1. 在**查詢**窗格中，新增下列變動：

   ```
   mutation addPost {
     addPost(
       id: 123,
       author: "AUTHORNAME"
       title: "Our first post!"
       content: "This is our first post."
       url: "https://aws.amazon.com/appsync/"
     ) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `addPost`。新建立的文章結果應該會出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "addPost": {
         "id": "123",
         "author": "AUTHORNAME",
         "title": "Our first post!",
         "content": "This is our first post.",
         "url": "https://aws.amazon.com/appsync/",
         "ups": 1,
         "downs": 0,
         "version": 1
       }
     }
   }
   ```

下列說明顯示發生的情況：

1. AWS AppSync 收到`addPost`變動請求。

1. AWS AppSync 會執行解析程式的請求處理常式。`ddb.put` 函數會建立如下所示的`PutItem`請求：

   ```
   {
     operation: 'PutItem',
     key: { id: { S: '123' } },
     attributeValues: {
       downs: { N: 0 },
       author: { S: 'AUTHORNAME' },
       ups: { N: 1 },
       title: { S: 'Our first post!' },
       version: { N: 1 },
       content: { S: 'This is our first post.' },
       url: { S: 'https://aws.amazon.com/appsync/' }
     }
   }
   ```

1. AWS AppSync 使用此值來產生和執行 Amazon DynamoDB `PutItem`請求。

1. AWS AppSync 取得`PutItem`請求的結果，並將其轉換回 GraphQL 類型。

   ```
   {
       "id" : "123",
       "author": "AUTHORNAME",
       "title": "Our first post!",
       "content": "This is our first post.",
       "url": "https://aws.amazon.com/appsync/",
       "ups" : 1,
       "downs" : 0,
       "version" : 1
   }
   ```

1. 回應處理常式會立即傳回結果 (`return ctx.result`)。

1. 最終結果會顯示在 GraphQL 回應中。

## 設定 getPost 解析程式 (Amazon DynamoDB GetItem)
<a name="configure-getpost"></a>

現在，您可以將資料新增至 Amazon DynamoDB 資料表，您需要設定`getPost`查詢，以便從資料表擷取該資料。若要執行此作業，您可以設定另一個解析程式。

**新增您的解析程式**

1. 在您的 API 中，選擇**結構描述**索引標籤。

1. 在右側**解析程式**窗格中，尋找 `Query`類型的 `getPost` 欄位，然後選擇**連接**。

1. 選擇您的資料來源，然後選擇**建立**。

1. 在程式碼編輯器中，使用此程式碼片段取代程式碼：

   ```
   import * as ddb from '@aws-appsync/utils/dynamodb'
   	
   export function request(ctx) {
   	return ddb.get({ key: { id: ctx.args.id } })
   }
   
   export const response = (ctx) => ctx.result
   ```

1. 儲存您的解析程式。

**注意**  
在此解析程式中，我們使用回應處理常式的箭頭函數表達式。

### 呼叫 API 以取得文章
<a name="call-api-getpost"></a>

現在已設定解析程式， AWS AppSync 知道如何將傳入的`getPost`查詢轉譯為 Amazon DynamoDB `GetItem`操作。您現在可以執行查詢，擷取您稍早建立的貼文。

**執行查詢**

1. 在您的 API 中，選擇**查詢**索引標籤。

1. 在**查詢**窗格中，新增下列程式碼，並使用您在建立文章後複製的 ID：

   ```
   query getPost {
     getPost(id: "123") {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `getPost`。新建立的文章結果應該會出現在**查詢**窗格右側的**結果**窗格中。

1. 從 Amazon DynamoDB 擷取的文章應該會出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "getPost": {
         "id": "123",
         "author": "AUTHORNAME",
         "title": "Our first post!",
         "content": "This is our first post.",
         "url": "https://aws.amazon.com/appsync/",
         "ups": 1,
         "downs": 0,
         "version": 1
       }
     }
   }
   ```

或者，請採用下列範例：

```
query getPost {
  getPost(id: "123") {
    id
    author
    title
  }
}
```

如果您的`getPost`查詢只需要 `id`、 `author`和 `title`，您可以將請求函數變更為使用投影表達式，以僅指定您想要從 DynamoDB 資料表傳輸的屬性，以避免從 DynamoDB 傳輸不必要的資料 AWS AppSync。例如，請求函數可能看起來像下面的程式碼片段：

```
import * as ddb from '@aws-appsync/utils/dynamodb'

export function request(ctx) {
	return ddb.get({
		key: { id: ctx.args.id },
		projection: ['author', 'id', 'title'],
	})
}

export const response = (ctx) => ctx.result
```

您也可以搭配 使用 [selectionSetList](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html#aws-appsync-resolver-context-reference-info-js) `getPost` 來代表 `expression`：

```
import * as ddb from '@aws-appsync/utils/dynamodb'

export function request(ctx) {
	const projection = ctx.info.selectionSetList.map((field) => field.replace('/', '.'))
	return ddb.get({ key: { id: ctx.args.id }, projection })
}

export const response = (ctx) => ctx.result
```

## 建立 updatePost 變動 (Amazon DynamoDB UpdateItem)
<a name="configure-updatepost"></a>

到目前為止，您可以在 Amazon DynamoDB 中建立和擷取`Post`物件。接著，您將設定新的變動來更新物件。相較於需要指定所有欄位的`addPost`變動，此變動可讓您只指定要變更的欄位。它還引入了一個新的`expectedVersion`引數，允許您指定要修改的版本。您將設定條件，以確保您正在修改物件的最新版本。您將使用 `UpdateItem` Amazon DynamoDB https：//operation.sc

**更新解析程式**

1. 在您的 API 中，選擇**結構描述**索引標籤。

1. 修改 **Schema (結構描述)** 窗格中的 `Mutation` 類型來新增 `updatePost` 變動，如下所示：

   ```
   type Mutation {
       updatePost(
           id: ID!,
           author: String,
           title: String,
           content: String,
           url: String,
           expectedVersion: Int!
       ): Post
       
       addPost(
           id: ID
           author: String!
           title: String!
           content: String!
           url: String!
       ): Post!
   }
   ```

1. 選擇 **Save Schema (儲存結構描述)**。

1. 在右側的**解析程式**窗格中，尋找`Mutation`類型上新建立`updatePost`的欄位，然後選擇**連接**。使用以下程式碼片段建立新的解析程式：

   ```
   import { util } from '@aws-appsync/utils';
   import * as ddb from '@aws-appsync/utils/dynamodb';
   
   export function request(ctx) {
     const { id, expectedVersion, ...rest } = ctx.args;
     const values = Object.entries(rest).reduce((obj, [key, value]) => {
       obj[key] = value ?? ddb.operations.remove();
       return obj;
     }, {});
   
     return ddb.update({
       key: { id },
       condition: { version: { eq: expectedVersion } },
       update: { ...values, version: ddb.operations.increment(1) },
     });
   }
   
   export function response(ctx) {
     const { error, result } = ctx;
     if (error) {
       util.appendError(error.message, error.type);
     }
     return result;
   ```

1. 儲存您所做的任何變更。

此解析程式使用 `ddb.update`來建立 Amazon DynamoDB `UpdateItem`請求。您只是要求 Amazon DynamoDB 更新特定屬性，而不是撰寫整個項目。這是使用 Amazon DynamoDB 更新表達式完成。

`ddb.update` 函數會採用金鑰和更新物件做為引數。然後，檢查傳入引數的值。將值設定為 時`null`，請使用 DynamoDB `remove`操作來表示應該從 DynamoDB 項目中移除該值。

也有新的`condition`區段。條件表達式可讓您在執行操作之前，根據 Amazon DynamoDB 中已存在的物件狀態，告知 AWS AppSync 和 Amazon DynamoDB 請求是否應成功。在此情況下，只有當 Amazon DynamoDB 中目前項目`version`的欄位完全符合`expectedVersion`引數時，您才希望`UpdateItem`請求成功。當項目更新時，我們希望增加 的值`version`。這很容易使用 操作函數 執行`increment`。

如需條件表達式的詳細資訊，請參閱[條件表達](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-condition-expressions)式文件。

如需`UpdateItem`請求的詳細資訊，請參閱 [UpdateItem](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-updateitem) 文件和 [DynamoDB 模組](https://docs.aws.amazon.com/appsync/latest/devguide/built-in-modules-js.html)文件。

如需有關如何撰寫更新表達式的詳細資訊，請參閱 [DynamoDB UpdateExpressions 文件](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html)。

### 呼叫 API 以更新文章
<a name="call-api-updatepost"></a>

讓我們嘗試使用新的解析程式更新`Post`物件。

**更新物件**

1. 在您的 API 中，選擇**查詢**索引標籤。

1. 在**查詢**窗格中，新增下列變動。您也需要將`id`引數更新為您先前記下的值：

   ```
   mutation updatePost {
     updatePost(
       id:123
       title: "An empty story"
       content: null
       expectedVersion: 1
     ) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `updatePost`。

1. Amazon DynamoDB 中更新的文章應該會出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "updatePost": {
         "id": "123",
         "author": "A new author",
         "title": "An empty story",
         "content": null,
         "url": "https://aws.amazon.com/appsync/",
         "ups": 1,
         "downs": 0,
         "version": 2
       }
     }
   }
   ```

在此請求中，您要求 AWS AppSync 和 Amazon DynamoDB 僅更新 `title`和 `content` 欄位。所有其他欄位都是單獨保留的 （非遞增`version`欄位）。您可以將 `title` 屬性設定為新值，並從文章中移除 `content` 屬性。`author`、`url`、`ups` 和 `downs` 欄位維持原狀。嘗試再次執行變動請求，同時完全離開請求。您應該會看到類似以下的回應：

```
{
  "data": {
    "updatePost": null
  },
  "errors": [
    {
      "path": [
        "updatePost"
      ],
      "data": null,
      "errorType": "DynamoDB:ConditionalCheckFailedException",
      "errorInfo": null,
      "locations": [
        {
          "line": 2,
          "column": 3,
          "sourceName": null
        }
      ],
      "message": "The conditional request failed (Service: DynamoDb, Status Code: 400, Request ID: 1RR3QN5F35CS8IV5VR4OQO9NNBVV4KQNSO5AEMVJF66Q9ASUAAJG)"
    }
  ]
}
```

請求失敗，因為條件表達式評估為 `false`：

1. 第一次執行請求時，Amazon DynamoDB 中文章的 `version` 欄位值為 `1`，符合 `expectedVersion`引數。請求成功，這表示 `version` 欄位已在 Amazon DynamoDB 中遞增至 `2`。

1. 第二次執行請求時，Amazon DynamoDB 中文章的 `version` 欄位值為 `2`，這不符合引`expectedVersion`數。

此模式通常稱為*樂觀鎖定*。

## 建立投票變動 (Amazon DynamoDB UpdateItem)
<a name="configure-vote-mutations"></a>

`Post` 類型包含 `ups`和 `downs` 欄位，以啟用上標和下標的記錄。不過，目前 API 不會讓我們對它們執行任何操作。讓我們新增變動，讓我們向上和向下移動文章。

**新增您的變動**

1. 在您的 API 中，選擇**結構描述**索引標籤。

1. 在**結構描述**窗格中，修改 `Mutation` 類型並新增`DIRECTION`列舉以新增新的投票變動：

   ```
   type Mutation {
       vote(id: ID!, direction: DIRECTION!): Post
       updatePost(
           id: ID!,
           author: String,
           title: String,
           content: String,
           url: String,
           expectedVersion: Int!
       ): Post
       addPost(
           id: ID,
           author: String!,
           title: String!,
           content: String!,
           url: String!
       ): Post!
   }
   
   enum DIRECTION {
     UP
     DOWN
   }
   ```

1. 選擇 **Save Schema (儲存結構描述)**。

1. 在右側的**解析程式**窗格中，尋找 `Mutation`類型上新建立`vote`的欄位，然後選擇**連接**。使用下列程式碼片段建立並取代程式碼，以建立新的解析程式：

   ```
   import * as ddb from '@aws-appsync/utils/dynamodb';
   
   export function request(ctx) {
     const field = ctx.args.direction === 'UP' ? 'ups' : 'downs';
     return ddb.update({
       key: { id: ctx.args.id },
       update: {
         [field]: ddb.operations.increment(1),
         version: ddb.operations.increment(1),
       },
     });
   }
   
   export const response = (ctx) => ctx.result;
   ```

1. 儲存您所做的任何變更。

### 呼叫 API 以上移或下移文章
<a name="call-api-vote"></a>

現在已設定新的解析程式， AWS AppSync 知道如何將傳入`upvotePost`或`downvote`變動轉譯為 Amazon DynamoDB `UpdateItem`操作。您現在可以執行變動，對您之前建立的文章表達贊同或不贊同。

**執行您的變動**

1. 在您的 API 中，選擇**查詢**索引標籤。

1. 在**查詢**窗格中，新增下列變動。您也需要將`id`引數更新為您先前記下的值：

   ```
   mutation votePost {
     vote(id:123, direction: UP) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `votePost`。

1. Amazon DynamoDB 中更新的文章應該會出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "vote": {
         "id": "123",
         "author": "A new author",
         "title": "An empty story",
         "content": null,
         "url": "https://aws.amazon.com/appsync/",
         "ups": 6,
         "downs": 0,
         "version": 4
       }
     }
   }
   ```

1. 選擇再**執行**幾次。每次執行查詢`1`時，您應該會看到 `ups`和 `version` 欄位遞增。

1. 變更查詢以使用不同的 呼叫它`DIRECTION`。

   ```
   mutation votePost {
     vote(id:123, direction: DOWN) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `votePost`。

   這次，您應該會看到 `downs`和 `version` 欄位`1`在您每次執行查詢時遞增。

## 設定 deletePost 解析程式 (Amazon DynamoDB DeleteItem)
<a name="configure-deletepost"></a>

接著，您會想要建立變動來刪除文章。您將使用 Amazon DynamoDB `DeleteItem` 操作來執行此操作。

**新增您的變動**

1. 在您的結構描述中，選擇**結構描述**索引標籤。

1. 在**結構描述**窗格中，修改 `Mutation`類型以新增新的`deletePost`變動：

   ```
   type Mutation {
       deletePost(id: ID!, expectedVersion: Int): Post
       vote(id: ID!, direction: DIRECTION!): Post
       updatePost(
           id: ID!,
           author: String,
           title: String,
           content: String,
           url: String,
           expectedVersion: Int!
       ): Post
       addPost(
           id: ID
           author: String!,
           title: String!,
           content: String!,
           url: String!
       ): Post!
   }
   ```

1. 這次，您將 `expectedVersion` 欄位設為選用。接著，選擇**儲存結構描述**。

1. 在右側的**解析程式**窗格中，尋找`Mutation`類型中新建立`delete`的欄位，然後選擇**連接**。使用下列程式碼建立新的解析程式：

   ```
   import { util } from '@aws-appsync/utils'
   
   import { util } from '@aws-appsync/utils';
   import * as ddb from '@aws-appsync/utils/dynamodb';
   
   export function request(ctx) {
     let condition = null;
     if (ctx.args.expectedVersion) {
       condition = {
         or: [
           { id: { attributeExists: false } },
           { version: { eq: ctx.args.expectedVersion } },
         ],
       };
     }
     return ddb.remove({ key: { id: ctx.args.id }, condition });
   }
   
   export function response(ctx) {
     const { error, result } = ctx;
     if (error) {
       util.appendError(error.message, error.type);
     }
     return result;
   }
   ```
**注意**  
`expectedVersion` 引數是選用的引數。如果發起人在請求中設定`expectedVersion`引數，請求處理常式會新增條件，只有在項目已刪除或 Amazon DynamoDB 中的文章`version`屬性完全符合 時，才會允許`DeleteItem`請求成功`expectedVersion`。如果省略，將不會在 `DeleteItem` 要求中指定條件表達式。無論值為 `version`或項目是否存在於 Amazon DynamoDB 中，它都會成功。  
即使您刪除項目，您也可以傳回已刪除的項目，如果該項目尚未刪除。

如需`DeleteItem`請求的詳細資訊，請參閱 [DeleteItem](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-deleteitem) 文件。

### 呼叫 API 以刪除文章
<a name="call-api-delete"></a>

現在已設定解析程式， AWS AppSync 知道如何將傳入`delete`的變動轉譯為 Amazon DynamoDB `DeleteItem`操作。您現在可以執行變動以在資料表中刪除項目。

**執行您的變動**

1. 在您的 API 中，選擇**查詢**索引標籤。

1. 在**查詢**窗格中，新增下列變動。您也需要將`id`引數更新為您先前記下的值：

   ```
   mutation deletePost {
     deletePost(id:123) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `deletePost`。

1. 文章會從 Amazon DynamoDB 刪除。請注意， 會 AWS AppSync 傳回從 Amazon DynamoDB 刪除的項目值，該值應該會出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "deletePost": {
         "id": "123",
         "author": "A new author",
         "title": "An empty story",
         "content": null,
         "url": "https://aws.amazon.com/appsync/",
         "ups": 6,
         "downs": 4,
         "version": 12
       }
     }
   }
   ```

1. 只有在此呼叫`deletePost`是實際從 Amazon DynamoDB 刪除的值時，才會傳回此值。再次選擇**執行**。

1. 呼叫仍然成功，但不會傳回任何值：

   ```
   {
     "data": {
       "deletePost": null
     }
   }
   ```

1. 現在，讓我們嘗試刪除文章，但這次指定 `expectedValue`。首先，您需要建立新的文章，因為您剛刪除了到目前為止一直使用的文章。

1. 在**查詢**窗格中，新增下列變動：

   ```
   mutation addPost {
     addPost(
       id:123
       author: "AUTHORNAME"
       title: "Our second post!"
       content: "A new post."
       url: "https://aws.amazon.com/appsync/"
     ) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `addPost`。

1. 新建立的文章結果應該會出現在**查詢**窗格右側的**結果**窗格中。記錄新建立物件`id`的 ，因為您只需要一點時間。其看起來與下列類似：

   ```
   {
     "data": {
       "addPost": {
         "id": "123",
         "author": "AUTHORNAME",
         "title": "Our second post!",
         "content": "A new post.",
         "url": "https://aws.amazon.com/appsync/",
         "ups": 1,
         "downs": 0,
         "version": 1
       }
     }
   }
   ```

1. 現在，讓我們嘗試刪除具有 **expectedVersion** 非法值的文章。在**查詢**窗格中，新增下列變動。您也需要將`id`引數更新為您先前記下的值：

   ```
   mutation deletePost {
     deletePost(
       id:123
       expectedVersion: 9999
     ) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `deletePost`。會傳回下列結果：

   ```
   {
     "data": {
       "deletePost": null
     },
     "errors": [
       {
         "path": [
           "deletePost"
         ],
         "data": null,
         "errorType": "DynamoDB:ConditionalCheckFailedException",
         "errorInfo": null,
         "locations": [
           {
             "line": 2,
             "column": 3,
             "sourceName": null
           }
         ],
         "message": "The conditional request failed (Service: DynamoDb, Status Code: 400, Request ID: 7083O037M1FTFRK038A4CI9H43VV4KQNSO5AEMVJF66Q9ASUAAJG)"
       }
     ]
   }
   ```

1. 請求失敗，因為條件表達式評估為 `false`。Amazon DynamoDB 中文章`version`的值與引數中`expectedValue`指定的 不相符。會在 GraphQL 回應 `data` 區段中 `errors` 欄位傳回物件的目前值。重試要求，但更正 `expectedVersion`：

   ```
   mutation deletePost {
     deletePost(
       id:123
       expectedVersion: 1
     ) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `deletePost`。

   這次請求成功，並傳回從 Amazon DynamoDB 刪除的值：

   ```
   {
     "data": {
       "deletePost": {
         "id": "123",
         "author": "AUTHORNAME",
         "title": "Our second post!",
         "content": "A new post.",
         "url": "https://aws.amazon.com/appsync/",
         "ups": 1,
         "downs": 0,
         "version": 1
       }
     }
   }
   ```

1. 再次選擇**執行**。呼叫仍然成功，但這次不會傳回任何值，因為文章已在 Amazon DynamoDB 中刪除。

   ```
   { "data": { "deletePost": null } }
   ```

## 設定 allPost 解析程式 (Amazon DynamoDB Scan)
<a name="configure-allpost"></a>

到目前為止，只有在您知道要查看的每個文章`id`的 時，API 才有用。讓我們新增新的解析程式，傳回資料表中的所有文章。

**新增您的變動**

1. 在您的 API 中，選擇**結構描述**索引標籤。

1. 修改 **Schema (結構描述)** 窗格中的 `Query` 類型以新增 `allPost` 查詢，如下所示：

   ```
   type Query {
       allPost(limit: Int, nextToken: String): PaginatedPosts!
       getPost(id: ID): Post
   }
   ```

1. 新增 `PaginationPosts` 類型：

   ```
   type PaginatedPosts {
       posts: [Post!]!
       nextToken: String
   }
   ```

1. 選擇 **Save Schema (儲存結構描述)**。

1. 在右側的**解析程式**窗格中，尋找 `Query`類型中新建立`allPost`的欄位，然後選擇**連接**。使用下列程式碼建立新的解析程式：

   ```
   import * as ddb from '@aws-appsync/utils/dynamodb';
   
   export function request(ctx) {
     const { limit = 20, nextToken } = ctx.arguments;
     return ddb.scan({ limit, nextToken });
   }
   
   export function response(ctx) {
     const { items: posts = [], nextToken } = ctx.result;
     return { posts, nextToken };
   }
   ```

   此解析程式的請求處理常式預期有兩個選用引數：
   + `limit` - 指定在單一呼叫中傳回的項目數量上限。
   + `nextToken` - 用來擷取下一組結果 （我們會顯示 的值稍後`nextToken`來自哪裡）。

1. 儲存對解析程式所做的任何變更。

如需`Scan`請求的詳細資訊，請參閱[掃描](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan)參考文件。

### 呼叫 API 以掃描所有文章
<a name="call-api-scan"></a>

現在已設定解析程式， AWS AppSync 知道如何將傳入的`allPost`查詢轉譯為 Amazon DynamoDB `Scan`操作。您現在可以掃描資料表來擷取所有文章。在您可以嘗試之前，您必須將一些資料填入資料表，因為您已刪除目前為止所使用的項目。

**新增和查詢資料 **

1. 在您的 API 中，選擇**查詢**索引標籤。

1. 在**查詢**窗格中，新增下列變動：

   ```
   mutation addPost {
     post1: addPost(id:1 author: "AUTHORNAME" title: "A series of posts, Volume 1" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
     post2: addPost(id:2 author: "AUTHORNAME" title: "A series of posts, Volume 2" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
     post3: addPost(id:3 author: "AUTHORNAME" title: "A series of posts, Volume 3" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
     post4: addPost(id:4 author: "AUTHORNAME" title: "A series of posts, Volume 4" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
     post5: addPost(id:5 author: "AUTHORNAME" title: "A series of posts, Volume 5" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
     post6: addPost(id:6 author: "AUTHORNAME" title: "A series of posts, Volume 6" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
     post7: addPost(id:7 author: "AUTHORNAME" title: "A series of posts, Volume 7" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
     post8: addPost(id:8 author: "AUTHORNAME" title: "A series of posts, Volume 8" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
     post9: addPost(id:9 author: "AUTHORNAME" title: "A series of posts, Volume 9" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title }
   }
   ```

1. 選擇**執行** （橘色播放按鈕）。

1. 現在，讓我們來掃描資料表，一次會傳回五個結果。在**查詢**窗格中，新增下列查詢：

   ```
   query allPost {
     allPost(limit: 5) {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `allPost`。

   前五篇文章應該會出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "allPost": {
         "posts": [
           {
             "id": "5",
             "title": "A series of posts, Volume 5"
           },
           {
             "id": "1",
             "title": "A series of posts, Volume 1"
           },
           {
             "id": "6",
             "title": "A series of posts, Volume 6"
           },
           {
             "id": "9",
             "title": "A series of posts, Volume 9"
           },
           {
             "id": "7",
             "title": "A series of posts, Volume 7"
           }
         ],
         "nextToken": "<token>"
       }
     }
   }
   ```

1. 您收到五個結果`nextToken`，以及可用來取得下一組結果的 。更新 `allPost` 查詢以包括來自之前結果組的 `nextToken`：

   ```
   query allPost {
     allPost(
       limit: 5
       nextToken: "<token>"
     ) {
       posts {
         id
         author
       }
       nextToken
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `allPost`。

   其餘四篇文章應該會出現在**查詢**窗格右側的**結果**窗格中。這組結果`nextToken`中沒有 ，因為您已翻閱全部九篇文章，沒有剩餘的文章。其看起來與下列類似：

   ```
   {
     "data": {
       "allPost": {
         "posts": [
           {
             "id": "2",
             "title": "A series of posts, Volume 2"
           },
           {
             "id": "3",
             "title": "A series of posts, Volume 3"
           },
           {
             "id": "4",
             "title": "A series of posts, Volume 4"
           },
           {
             "id": "8",
             "title": "A series of posts, Volume 8"
           }
         ],
         "nextToken": null
       }
     }
   }
   ```

## 設定 allPostsByAuthor 解析程式 (Amazon DynamoDB 查詢）
<a name="configure-query"></a>

除了掃描 Amazon DynamoDB 的所有文章之外，您也可以查詢 Amazon DynamoDB 以擷取特定作者建立的文章。您先前建立的 Amazon DynamoDB 資料表已有`GlobalSecondaryIndex`稱為 的 `author-index`，您可以搭配 Amazon DynamoDB `Query`操作使用，以擷取特定作者建立的所有文章。

**新增查詢**

1. 在您的 API 中，選擇**結構描述**索引標籤。

1. 修改 **Schema (結構描述)** 窗格中的 `Query` 類型以新增 `allPostsByAuthor` 查詢，如下所示：

   ```
   type Query {
       allPostsByAuthor(author: String!, limit: Int, nextToken: String): PaginatedPosts!
       allPost(limit: Int, nextToken: String): PaginatedPosts!
       getPost(id: ID): Post
   }
   ```

   請注意，這使用與`allPost`查詢相同的`PaginatedPosts`類型。

1. 選擇 **Save Schema (儲存結構描述)**。

1. 在右側的**解析程式**窗格中，尋找 `Query`類型上新建立`allPostsByAuthor`的欄位，然後選擇**連接**。使用以下程式碼片段建立解析程式：

   ```
   import * as ddb from '@aws-appsync/utils/dynamodb';
   
   export function request(ctx) {
     const { limit = 20, nextToken, author } = ctx.arguments;
     return ddb.query({
       index: 'author-index',
       query: { author: { eq: author } },
       limit,
       nextToken,
     });
   }
   
   export function response(ctx) {
     const { items: posts = [], nextToken } = ctx.result;
     return { posts, nextToken };
   }
   ```

   如同`allPost`解析程式，此解析程式有兩個選用引數：
   + `limit` - 指定在單一呼叫中傳回的項目數量上限。
   + `nextToken` - 擷取下一組結果 ( 的值`nextToken`可從先前的呼叫取得）。

1. 儲存對解析程式所做的任何變更。

如需`Query`請求的詳細資訊，請參閱[查詢](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-query)參考文件。

### 呼叫 API 以依作者查詢所有文章
<a name="call-api-query"></a>

現在已設定解析程式， AWS AppSync 知道如何針對`author-index`索引將傳入`allPostsByAuthor`的變動轉換為 DynamoDB `Query`操作。您現在可以查詢資料表以擷取特定作者的所有文章。

不過，在此之前，讓我們將更多文章填入資料表，因為到目前為止，每篇文章都有相同的作者。

**新增資料和查詢**

1. 在您的 API 中，選擇**查詢**索引標籤。

1. 在**查詢**窗格中，新增下列變動：

   ```
   mutation addPost {
     post1: addPost(id:10 author: "Nadia" title: "The cutest dog in the world" content: "So cute. So very, very cute." url: "https://aws.amazon.com/appsync/" ) { author, title }
     post2: addPost(id:11 author: "Nadia" title: "Did you know...?" content: "AppSync works offline?" url: "https://aws.amazon.com/appsync/" ) { author, title }
     post3: addPost(id:12 author: "Steve" title: "I like GraphQL" content: "It's great" url: "https://aws.amazon.com/appsync/" ) { author, title }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `addPost`。

1. 現在，讓我們查詢資料表，傳回 `Nadia` 撰寫的所有文章。在**查詢**窗格中，新增下列查詢：

   ```
   query allPostsByAuthor {
     allPostsByAuthor(author: "Nadia") {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `allPostsByAuthor`。撰寫的所有文章`Nadia`都應出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "allPostsByAuthor": {
         "posts": [
           {
             "id": "10",
             "title": "The cutest dog in the world"
           },
           {
             "id": "11",
             "title": "Did you know...?"
           }
         ],
         "nextToken": null
       }
     }
   }
   ```

1. 分頁適用於 `Query`，如同它適用於 `Scan`。例如，讓我們查詢 `AUTHORNAME` 的所有文章，一次取得五篇。

1. 在**查詢**窗格中，新增下列查詢：

   ```
   query allPostsByAuthor {
     allPostsByAuthor(
       author: "AUTHORNAME"
       limit: 5
     ) {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `allPostsByAuthor`。撰寫的所有文章`AUTHORNAME`都應出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "allPostsByAuthor": {
         "posts": [
           {
             "id": "6",
             "title": "A series of posts, Volume 6"
           },
           {
             "id": "4",
             "title": "A series of posts, Volume 4"
           },
           {
             "id": "2",
             "title": "A series of posts, Volume 2"
           },
           {
             "id": "7",
             "title": "A series of posts, Volume 7"
           },
           {
             "id": "1",
             "title": "A series of posts, Volume 1"
           }
         ],
         "nextToken": "<token>"
       }
     }
   }
   ```

1. 使用之前查詢傳回的值更新 `nextToken` 引數，如下所示：

   ```
   query allPostsByAuthor {
     allPostsByAuthor(
       author: "AUTHORNAME"
       limit: 5
       nextToken: "<token>"
     ) {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `allPostsByAuthor`。撰寫的其餘文章`AUTHORNAME`應該會出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "allPostsByAuthor": {
         "posts": [
           {
             "id": "8",
             "title": "A series of posts, Volume 8"
           },
           {
             "id": "5",
             "title": "A series of posts, Volume 5"
           },
           {
             "id": "3",
             "title": "A series of posts, Volume 3"
           },
           {
             "id": "9",
             "title": "A series of posts, Volume 9"
           }
         ],
         "nextToken": null
       }
     }
   }
   ```

## 使用集合
<a name="using-sets"></a>

到目前為止， `Post`類型是扁平索引鍵/值物件。您也可以使用解析程式建立複雜物件的模型，例如集合、清單和映射。讓我們將 `Post` 類型更新為包含標籤。文章可以有零或多個標籤，這些標籤會以字串集的形式存放在 DynamoDB 中。您也會設定一些變動來新增和移除標籤，以及新查詢以掃描含特定標籤的文章。

**設定您的資料**

1. 在您的 API 中，選擇**結構描述**索引標籤。

1. 修改 **Schema (結構描述)** 窗格中的 `Post` 類型以新增 `tags` 欄位，如下所示：

   ```
   type Post {
     id: ID!
     author: String
     title: String
     content: String
     url: String
     ups: Int!
     downs: Int!
     version: Int!
     tags: [String!]
   }
   ```

1. 修改 **Schema (結構描述)** 窗格中的 `Query` 類型以新增 `allPostsByTag` 查詢，如下所示：

   ```
   type Query {
     allPostsByTag(tag: String!, limit: Int, nextToken: String): PaginatedPosts!
     allPostsByAuthor(author: String!, limit: Int, nextToken: String): PaginatedPosts!
     allPost(limit: Int, nextToken: String): PaginatedPosts!
     getPost(id: ID): Post
   }
   ```

1. 修改 **Schema (結構描述)** 窗格中的 `Mutation` 類型以新增 `addTag` 和 `removeTag` 變動，如下所示：

   ```
   type Mutation {
     addTag(id: ID!, tag: String!): Post
     removeTag(id: ID!, tag: String!): Post
     deletePost(id: ID!, expectedVersion: Int): Post
     upvotePost(id: ID!): Post
     downvotePost(id: ID!): Post
     updatePost(
       id: ID!,
       author: String,
       title: String,
       content: String,
       url: String,
       expectedVersion: Int!
     ): Post
     addPost(
       author: String!,
       title: String!,
       content: String!,
       url: String!
     ): Post!
   }
   ```

1. 選擇 **Save Schema (儲存結構描述)**。

1. 在右側的**解析程式**窗格中，尋找 `Query`類型上新建立`allPostsByTag`的欄位，然後選擇**連接**。使用以下程式碼片段建立您的解析程式：

   ```
   import * as ddb from '@aws-appsync/utils/dynamodb';
   
   export function request(ctx) {
     const { limit = 20, nextToken, tag } = ctx.arguments;
     return ddb.scan({ limit, nextToken, filter: { tags: { contains: tag } } });
   }
   
   export function response(ctx) {
     const { items: posts = [], nextToken } = ctx.result;
     return { posts, nextToken };
   }
   ```

1. 儲存您對解析程式所做的任何變更。

1. 現在，`addTag`使用下面的程式碼片段對 `Mutation` 欄位執行相同的操作：
**注意**  
雖然 DynamoDB 公用程式目前不支援集合操作，但您仍可自行建置請求來與集合互動。

   ```
   import { util } from '@aws-appsync/utils'
   
   export function request(ctx) {
   	const { id, tag } = ctx.arguments
   	const expressionValues = util.dynamodb.toMapValues({ ':plusOne': 1 })
   	expressionValues[':tags'] = util.dynamodb.toStringSet([tag])
   
   	return {
   		operation: 'UpdateItem',
   		key: util.dynamodb.toMapValues({ id }),
   		update: {
   			expression: `ADD tags :tags, version :plusOne`,
   			expressionValues,
   		},
   	}
   }
   
   export const response = (ctx) => ctx.result
   ```

1. 儲存對解析程式所做的任何變更。

1. `removeTag` 使用以下程式碼片段對 `Mutation` 欄位重複此操作一次：

   ```
   import { util } from '@aws-appsync/utils';
   	
   export function request(ctx) {
   	  const { id, tag } = ctx.arguments;
   	  const expressionValues = util.dynamodb.toMapValues({ ':plusOne': 1 });
   	  expressionValues[':tags'] = util.dynamodb.toStringSet([tag]);
   	
   	  return {
   	    operation: 'UpdateItem',
   	    key: util.dynamodb.toMapValues({ id }),
   	    update: {
   	      expression: `DELETE tags :tags ADD version :plusOne`,
   	      expressionValues,
   	    },
   	  };
   	}
   	
   	export const response = (ctx) => ctx.resultexport
   ```

1. 儲存對解析程式所做的任何變更。

### 呼叫 API 來使用標籤
<a name="call-api-tags"></a>

現在您已設定解析程式， AWS AppSync 知道如何將傳入的 `removeTag`、 `addTag`和 `allPostsByTag`請求轉譯為 DynamoDB `UpdateItem`和 `Scan`操作。為了嘗試看看，讓我們選擇您先前建立的其中一篇文章。例如，讓我們使用 `Nadia` 撰寫的一篇文章。

**使用標籤**

1. 在您的 API 中，選擇**查詢**索引標籤。

1. 在**查詢**窗格中，新增下列查詢：

   ```
   query allPostsByAuthor {
     allPostsByAuthor(
       author: "Nadia"
     ) {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `allPostsByAuthor`。

1. Nadia 的所有文章都應出現在**查詢**窗格右側的**結果**窗格中。其看起來與下列類似：

   ```
   {
     "data": {
       "allPostsByAuthor": {
         "posts": [
           {
             "id": "10",
             "title": "The cutest dog in the world"
           },
           {
             "id": "11",
             "title": "Did you known...?"
           }
         ],
         "nextToken": null
       }
     }
   }
   ```

1. 讓我們使用標題*為 全世界最可愛的狗*。記錄它，`id`因為您稍後會用到它。現在，讓我們嘗試新增`dog`標籤。

1. 在**查詢**窗格中，新增下列變動。您也必須將 `id` 引數更新為您先前記下的值。

   ```
   mutation addTag {
     addTag(id:10 tag: "dog") {
       id
       title
       tags
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `addTag`。文章會以新標籤更新：

   ```
   {
     "data": {
       "addTag": {
         "id": "10",
         "title": "The cutest dog in the world",
         "tags": [
           "dog"
         ]
       }
     }
   }
   ```

1. 您可以新增更多標籤。更新變動以將`tag`引數變更為 `puppy`：

   ```
   mutation addTag {
     addTag(id:10 tag: "puppy") {
       id
       title
       tags
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `addTag`。文章會以新標籤更新：

   ```
   {
     "data": {
       "addTag": {
         "id": "10",
         "title": "The cutest dog in the world",
         "tags": [
           "dog",
           "puppy"
         ]
       }
     }
   }
   ```

1. 您也可以刪除標籤。在**查詢**窗格中，新增下列變動。您也需要將`id`引數更新為您先前記下的值：

   ```
   mutation removeTag {
     removeTag(id:10 tag: "puppy") {
       id
       title
       tags
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `removeTag`。貼文將會更新，且 `puppy` 標籤將會刪除。

   ```
   {
     "data": {
       "addTag": {
         "id": "10",
         "title": "The cutest dog in the world",
         "tags": [
           "dog"
         ]
       }
     }
   }
   ```

1. 您也可以搜尋具有標籤的所有文章。在**查詢**窗格中，新增下列查詢：

   ```
   query allPostsByTag {
     allPostsByTag(tag: "dog") {
       posts {
         id
         title
         tags
       }
       nextToken
     }
   }
   ```

1. 選擇**執行** （橘色播放按鈕），然後選擇 `allPostsByTag`。具有 `dog` 標籤的所有文章將會傳回，如下所示：

   ```
   {
     "data": {
       "allPostsByTag": {
         "posts": [
           {
             "id": "10",
             "title": "The cutest dog in the world",
             "tags": [
               "dog",
               "puppy"
             ]
           }
         ],
         "nextToken": null
       }
     }
   }
   ```

## 結論
<a name="conclusion-dynamodb-tutorial-js"></a>

在本教學課程中，您已建置 API，可讓您使用 AWS AppSync 和 GraphQL 在 DynamoDB 中操作`Post`物件。

若要清除，您可以從主控台刪除 AWS AppSync GraphQL API。

若要刪除與 DynamoDB 資料表相關聯的角色，請在資料來源資料表中選取**您的資料來源**，然後按一下**編輯**。在**建立或使用現有**角色下記下角色的值。前往 IAM 主控台以刪除角色。

若要刪除 DynamoDB 資料表，請按一下資料來源清單中的資料表名稱。這會帶您前往 DynamoDB 主控台，您可以在其中刪除資料表。