

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# 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 をセットアップでき、このチュートリアルの残りの部分でクエリを実行できます。

## 基本的な Post API の定義
<a name="define-post-api"></a>

ここで、GraphQL API があるので、ポストデータの基本的な作成、取得、削除を許可する基本スキーマをセットアップできます。

**スキーマにデータを追加するには**

1. API で **[スキーマ]** タブを選択します。

1. `Post` オブジェクトを追加および取得するための `Post` タイプと操作 `addPost` を定義するスキーマを作成します。**[スキーマ]** ペインで、内容を次のコードに置き換えます。

   ```
   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 リゾルバー (DAmazon DynamoDB PutItem) のセットアップ
<a name="configure-addpost"></a>

 AWS AppSync が Amazon DynamoDB テーブルを認識したので、リゾルバーを定義することで、個々のクエリとミューテーションにリンクできます。最初に作成するリゾルバーは `addPost` リゾルバーです。このリゾルバーによって、ユーザーが Amazon DynamoDB テーブルにポストを作成できるようになります。パイプラインリゾルバーには以下のコンポーネントがあります。
+ リゾルバーをアタッチする、GraphQL スキーマ内の場所。この例では、`createPost` 型の `Mutation` フィールドにリゾルバーをセットアップしています。このリゾルバーは、呼び出し元がミューテーション `{ addPost(...){...} }` を呼び出したときに呼び出されます。
+ このリゾルバーで使用するデータソース。この例では、`post-table-for-tutorial` DynamoDB テーブルにエントリを追加できるように、前に定義した データソースを使用します。
+ リクエストハンドラー。リクエストハンドラーは、発信者からの受信リクエストを処理し、それを が DynamoDB に対して実行する手順に変換 AWS AppSync する関数です。
+ レスポンスハンドラー。レスポンスハンドラーの仕事は、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 リクエストを簡単に作成できる DynamoDB モジュール utils を使用します。

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>

リゾルバーが設定されたので、 は着信`addPost`ミューテーションを Amazon DynamoDB `PutItem`オペレーションに変換 AWS AppSync できます。ユーザーはミューテーションを実行してテーブルに何かを入れることができるようになりました。

**オペレーションを実行するには**

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>

リゾルバーがセットアップされたので、 は受信`getPost`クエリを Amazon DynamoDB `GetItem`オペレーションに変換する方法 AWS AppSync を理解します。次は、先ほど作成したポストを取得するクエリを実行します。

**クエリを実行するには**

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 から AWS AppSyncへの不要なデータ転送を避けるため、プロジェクション式を使用して DynamoDB テーブルから必要な属性のみを指定するようにリクエスト関数を変更できます。例えば、リクエスト関数は以下のスニペットのようになっているかもしれません。

```
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 operation.sc を使用します。

**リゾルバーを更新するには**

1. API で **[スキーマ]** タブを選択します。

1. **[スキーマ]** ペインの `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` 引数と一致していました。このリクエストは成功し、Amazon DynamoDB で `version` フィールドが `2` に増分されました。

1. このリクエストを 2 回目に実行したときに、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>

新しいリゾルバーがセットアップされたので、 は受信`upvotePost`または`downvote`ミューテーションを Amazon DynamoDB `UpdateItem`オペレーションに変換する方法 AWS AppSync を理解します。これで、先ほど作成したポストに賛成または反対するミューテーションを実行できるようになりました。

**ミューテーションを実行するには**

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. もう何回か **[実行]** を選択します。このクエリを実行するたびに、`ups` フィールドと `version` フィールドが `1` つずつ増加することを確認できます。

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>

次に、投稿を削除するミューテーションを作成します。そのためには、`DeleteItem` Amazon DynamoDB オペレーションを使用します。

**ミューテーションを追加するには**

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. 右側の **[リゾルバー]** ペインで、`delete` タイプから新しく作成された `Mutation` フィールドを探し、**[アタッチ]** を選択します。次のコードを使用して新しいリゾルバーを作成します。

   ```
   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` 属性が `expectedVersion` と完全に一致する場合にのみ、`DeleteItem` リクエストが成功することを許可する条件が、テンプレートによって追加されます。この引数が省略されている場合は、`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>

リゾルバーがセットアップされたので、 は着信`delete`ミューテーションを Amazon DynamoDB `DeleteItem`オペレーションに変換する方法 AWS AppSync を理解します。ユーザーはミューテーションを実行してテーブル内の何かを削除できるようになりました。

**ミューテーションを実行するには**

1. API で **[クエリ]** タブを選択します。

1. 以下のミューテーションを **[クエリ]** ペインに貼り付けます。また、`id` 引数を、前にメモしておいた値に更新する必要があります。

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

1. **[実行]** (オレンジ色の再生ボタン) を選択し、[`deletePost`] を選択します。

1. この投稿が Amazon DynamoDB から削除されます。は、Amazon DynamoDB から削除された項目の値 AWS AppSync を返します。この値は、**クエリ**ペインの右側にある**結果**ペインに表示されます。これは次のように表示されます。

   ```
   {
     "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>

これまでのところ、API は、見たい各投稿の `id` がわかっている場合にのみ便利です。テーブル内のすべてのポストを返す新しいリゾルバーを追加してみましょう。

**ミューテーションを追加するには**

1. API で **[スキーマ]** タブを選択します。

1. **[スキーマ]** ペインの `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. 右側の **[リゾルバー]** ペインで、`allPost` タイプから新しく作成された `Query` フィールドを探し、**[アタッチ]** を選択します。次のコードを使用して新しいリゾルバーを作成します。

   ```
   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 };
   }
   ```

   このリゾルバーのリクエストハンドラーには 2 つのオプション引数が必要です。
   + `limit` - 1 回の呼び出しで返される項目の最大数を指定します。
   + `nextToken` - 次の結果セットを取得するために使用されます (`nextToken`の値がどこから来たのかは後で説明します)。

1. リゾルバーに加えた変更を保存します。

`Scan` リクエストの詳細については、「[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>

リゾルバーがセットアップされたので、 は受信`allPost`クエリを Amazon DynamoDB `Scan`オペレーションに変換する方法 AWS AppSync を理解します。ユーザーは、テーブルをスキャンしてすべてのポストを取得できるようになりました。ただし、これまで使用してきたデータはすべて削除したため、これを試す前にテーブルにデータを入力しておく必要があります。

**データを追加してクエリするには**

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. では、テーブルをスキャンして、一度に 5 個の結果を返しましょう。以下のクエリを**クエリ**ペインに貼り付けます。

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

1. **[実行]** (オレンジ色の再生ボタン) を選択し、[`allPost`] を選択します。

   最初の 5 個のポストが、**クエリ**ペインの右側にある**結果**ペインに表示されます。これは次のように表示されます。

   ```
   {
     "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. 5 つの結果と `nextToken` を取得しました。このトークンを使用して、次の結果セットを取得できます。前回の結果セットからの `allPost` を含めるように、`nextToken` クエリを更新します。

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

1. **[実行]** (オレンジ色の再生ボタン) を選択し、[`allPost`] を選択します。

   残りの 4 個のポストが、**クエリ**ペインの右側にある**結果**ペインに表示されます。9 個のポストのすべてをページ分割して、ポストは残っていないため、この結果セットに `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 テーブルには、既に `author-index` という `GlobalSecondaryIndex` があるため、Amazon DynamoDB の `Query` オペレーションでそれを使用して、特定の作成者が作成したすべてのポストを取得できます

**クエリを追加するには**

1. API で **[スキーマ]** タブを選択します。

1. **[スキーマ]** ペインの `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. 右側の**リゾルバー**ペインで、`allPostsByAuthor` 型の新しく作成された `Query` フィールドを見つけて、[**アタッチ**] を選択します。以下のスニペットを使用してリゾルバーを作成します。

   ```
   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` リゾルバーと同様に、このリゾルバーには 2 つのオプション引数があります。
   + `limit` - 1 回の呼び出しで返される項目の最大数を指定します。
   + `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>

リゾルバーがセットアップされたので、 は受信`allPostsByAuthor`ミューテーションを`author-index`インデックスに対する DynamoDB `Query`オペレーションに変換する方法 AWS AppSync を理解します。ユーザーは、テーブルをクエリして、特定の作成者によるポストをすべて取得できます。

ただし、これまで使用していたポストはすべて同じ作成者だったため、それを行う前に、テーブルに投稿を追加しておきましょう。

**データとクエリを追加するには**

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` によるすべてのポストを検索して、一度に 5 個ずつ取得します。

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` 型を更新して、タグを含めましょう。1 つのポストには、DynamoDB に文字列として保存されているタグを 0 個以上付けることができます。タグを追加および削除するミューテーションと、特定のタグが付いているポストをスキャンする新しいクエリもセットアップします。

**データを設定するには**

1. API で **[スキーマ]** タブを選択します。

1. **[スキーマ]** ペインの `Post` タイプを次のように変更して、新しい `tags` フィールドを追加します。

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

1. **[スキーマ]** ペインの `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. **[スキーマ]** ペインの `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. 右側の**リゾルバー**ペインで、`allPostsByTag` 型の新しく作成された `Query` フィールドを見つけて、[**アタッチ**] を選択します。以下のスニペットを使用してリゾルバーを作成します。

   ```
   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. 次に、以下のスニペットを使って`Mutation` フィールド `addTag` に対して同じ操作を行います。
**注記**  
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. 以下のスニペットを使用して、これを `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>

リゾルバーをセットアップしたので、 は受信 `addTag`、、`removeTag`および `allPostsByTag`リクエストを DynamoDB `UpdateItem`および `Scan`オペレーションに変換する方法 AWS AppSync を理解しています。それを試すには、前のステップで作成したポストのいずれかを選択します。例えば、`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. タイトルが「*The cutest dog in the world*」の投稿を使用しましょう。`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. タグを追加することができます。`puppy` に変更するように、`tag` 引数を更新します。

   ```
   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>

このチュートリアルでは、 AWS AppSync と GraphQL を使用して `Post` オブジェクトを操作できる API を構築しました。

クリーンアップするには、 コンソールから AWS AppSync GraphQL API を削除できます。

DynamoDB テーブルに関連付けられているロールを削除するには、**[データソース]** テーブルで [データソース]を選択し、**[編集]** をクリックします。**[既存のロールを作成または使用する]** の下にあるロールの値を書き留めます。IAM コンソールに移動して、ロールを削除します。

DynamoDB テーブルを削除するには、データソースリスト内のテーブルの名前をクリックします。これにより、DynamoDB コンソールに移動して、テーブルを削除できます。