翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
DynamoDB リゾルバーを使用したシンプルなポストアプリケーションの作成
注記
現在、主に APPSYNC_JS ランタイムとそのドキュメントをサポートしています。こちら で APPSYNC_JS ランタイムとそのガイドの使用をご検討ください。
このチュートリアルでは、独自の Amazon DynamoDB テーブルを AWS AppSync に持ち込み、GraphQL API に接続する方法を示します。
ユーザーに代わって DynamoDB リソースをプロビジョニングすることを AWS AppSync に許可できます。または、必要であれば、データソースとリゾルバーを作成することで、既存のテーブルを GraphQL スキーマに接続できます。いずれの場合も、GraphQL ステートメントを使用して DynamoDB データベースへの読み取りと書き込みを行うことができ、リアルタイムデータをサブスクライブできます。
GraphQL ステートメントが DynamoDB オペレーションに変換され、レスポンスが GraphQL に変換されるように、特定の設定ステップを完了しておく必要があります。このチュートリアルでは、いくつかの実際のシナリオおよびデータアクセスパターンを使用して、その設定手順の概要を示します。
DynamoDB テーブルのセットアップ
このチュートリアルを開始するには、まず以下の手順に従って AWS リソースをプロビジョニングする必要があります。
-
CLI で次の AWS CloudFormation テンプレートを使用して AWS リソースをプロビジョニングします。
aws cloudformation create-stack \ --stack-name AWSAppSyncTutorialForAmazonDynamoDB \ --template-url https://s3.us-west-2.amazonaws.com/awsappsync/resources/dynamodb/AmazonDynamoDBCFTemplate.yaml \ --capabilities CAPABILITY_NAMED_IAMまたは、アカウントの米国西部 2 (オレゴン) リージョンで次の AWS CloudFormation スタックを起動することもできます AWS 。
これにより、以下の項目が作成されます。
-
データを保持するDynamoDBテーブルが
AppSyncTutorial-Post呼び出されます。Post -
AWS AppSync が
Postテーブルとやり取りできるようにする IAM ロールおよび関連する IAM 管理ポリシー。
-
-
スタックおよび作成されたリソースに関する詳細を確認するには、次の CLI コマンドを実行します。
aws cloudformation describe-stacks --stack-name AWSAppSyncTutorialForAmazonDynamoDB -
そのリソースを削除するには、次のコマンドを実行します。
aws cloudformation delete-stack --stack-name AWSAppSyncTutorialForAmazonDynamoDB
GraphQL API の作成
AWS AppSync で GraphQL API を作成するには:
-
にサインイン AWS Management Console し、AppSync コンソール
を開きます。 -
API ダッシュボードで、[API の作成] を選択します。
-
-
[API をカスタマイズまたは Amazon DynamoDB からインポート] ウィンドウで、[一から構築] を選択します。
-
同じウィンドウの右にある [開始] を選択します。
-
-
[API 名] フィールドで、API の名前を
AWSAppSyncTutorialに設定します。 -
[作成] を選択します。
AWS AppSync コンソールは、API キー認証モードを使用して新しい GraphQL API を作成します。このコンソールを使用して、残りの GraphQL API をセットアップでき、このチュートリアルの残りの部分でクエリを実行できます。
基本的な Post API の定義
AWS AppSync GraphQL API を作成したので、ポストデータの基本的な作成、取得、削除を許可する基本スキーマを設定できます。
-
にサインイン AWS Management Console し、AppSync コンソール
を開きます。 -
API ダッシュボードで、先ほど作成した API を選択します。
-
-
サイドバーで [スキーマ] を選択します。
-
[スキーマ] ペインで、内容を次のコードに置き換えます。
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! }
-
-
[保存] を選択します。
このスキーマでは、Post 型と、Post オブジェクトを追加および取得するオペレーションを定義しています。
DynamoDB テーブル用のデータソースの設定
次に、スキーマで定義されているクエリとミューテーションを AppSyncTutorial-Post DynamoDB テーブルにリンクします。
まず、 AWS AppSync はテーブルを認識する必要があります。これを行うには AWS AppSync にデータソースをセットアップします。
-
にサインイン AWS Management Console し、AppSync コンソール
を開きます。 -
API ダッシュボードで、GraphQL API を選択します。
-
サイドバー で [データソース] を選択します。
-
-
[データソースを作成] を選択します。
-
データソース名には、
PostDynamoDBTableを入力します。 -
[データソースタイプ] として [Amazon DynamoDB テーブル] を選択します。
-
[リージョン] として [US-WEST-2] を選択します。
-
[テーブル名] には、[AppSyncTutorial-Post] DynamoDB テーブルを選択します。
-
次に、新しい IAM ロールを作成するか (推奨)、
lambda:invokeFunctionへの IAM アクセス許可を持つ既存のロールを選択します。データソースのアタッチセクションで説明しているように、既存のロールには信頼ポリシーが必要です。次に、リソースで操作を実行するために必要なアクセス許可を持つ IAM ポリシーの例を示します。
-
-
[作成] を選択します。
addPost リゾルバー (DynamoDB PutItem) のセットアップ
AWS AppSync が DynamoDB テーブルを認識したら、リゾルバーを定義して個々のクエリとミューテーションにリンクできます。最初に作成するリゾルバーは addPost リゾルバーです。このリゾルバーによって、ユーザーが AppSyncTutorial-Post DynamoDB テーブルにポストを作成できるようになります。
リゾルバーには以下のコンポーネントがあります。
-
リゾルバーをアタッチする、GraphQL スキーマ内の場所。この例では、
addPost型のMutationフィールドにリゾルバーをセットアップしています。このリゾルバーは、呼び出し元がmutation { addPost(...){...} }を呼び出したときに呼び出されます。 -
このリゾルバーで使用するデータソース。この例では、
PostDynamoDBTableDynamoDB テーブルにエントリを追加できるように、前に定義したAppSyncTutorial-Postデータソースを使用します。 -
リクエストマッピングテンプレート。リクエストマッピングテンプレートの目的は、発信者からの受信リクエストを受け取り、それを AWS AppSync が DynamoDB に対して実行する手順に変換することです。
-
レスポンスマッピングテンプレート。レスポンスマッピングテンプレートの目的は、DynamoDB からのレスポンスを取り込み、それを GraphQL で想定されているものに変換し直すことです。これは、DynamoDB でのデータのシェイプが GraphQL での
Post型と異なる場合に便利です。ただし、この例では、両方のシェイプが同じであるため、データをそのまま渡します。
リゾルバーをセットアップするには、以下の手順に従います。
-
にサインイン AWS Management Console し、AppSync コンソール
を開きます。 -
API ダッシュボードで、GraphQL API を選択します。
-
サイドバー で [データソース] を選択します。
-
-
[データソースを作成] を選択します。
-
データソース名には、
PostDynamoDBTableを入力します。 -
[データソースタイプ] として [Amazon DynamoDB テーブル] を選択します。
-
[リージョン] として [US-WEST-2] を選択します。
-
[テーブル名] には、[AppSyncTutorial-Post] DynamoDB テーブルを選択します。
-
次に、新しい IAM ロールを作成するか (推奨)、
lambda:invokeFunctionへの IAM アクセス許可を持つ既存のロールを選択します。データソースのアタッチセクションで説明しているように、既存のロールには信頼ポリシーが必要です。次に、リソースで操作を実行するために必要なアクセス許可を持つ IAM ポリシーの例を示します。
-
-
[作成] を選択します。
-
[Schema (スキーマ)] タブを選択します。
-
右側のデータ型ペインで、ミューテーション型のaddPostフィールドを見つけて、アタッチを選択します。
-
[アクション] メニューで [ランタイムの更新] を選択し、[ユニットリゾルバー (VTL のみ)] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "attributeValues" : { "author" : $util.dynamodb.toDynamoDBJson($context.arguments.author), "title" : $util.dynamodb.toDynamoDBJson($context.arguments.title), "content" : $util.dynamodb.toDynamoDBJson($context.arguments.content), "url" : $util.dynamodb.toDynamoDBJson($context.arguments.url), "ups" : { "N" : 1 }, "downs" : { "N" : 0 }, "version" : { "N" : 1 } } }注 : 「型」はすべてのキーと属性値で指定されています。例えば、
authorフィールドを{ "S" : "${context.arguments.author}" }に設定します。S部分は、値が文字列値になることを to AWS AppSync と DynamoDB に示します。実際の値はauthor引数から入力されます。同様に、versionフィールドは、型としてNが使用されているため数値フィールドです。最後に、ups、downsおよびversionフィールドの初期化も行っています。このチュートリアルでは、DynamoDB に挿入される新しい項目のインデックスを作成する GraphQL
ID!タイプが、クライアント arguments. AWS AppSync comes の一部として、 という名前の自動 ID 生成用のユーティリティとともに提供されることを指定しました。$utils.autoId()これは、 の形式でも使用できます"id" : { "S" : "${$utils.autoId()}" }。そのため、id: ID!をaddPost()のスキーマ定義から除外するだけで、自動的に挿入されます。このチュートリアルではこの手法を使用しませんが、DynamoDB テーブルに書き込む場合はこの手法を検討することをお勧めします。マッピングテンプレートの詳細については、「リゾルバーのマッピングテンプレートの概要」リファレンスドキュメントを参照してください。GetItem リクエストマッピングの詳細については、「GetItem」リファレンスドキュメントを参照してください。型の詳細については、「型システム (リクエストマッピング)」リファレンスドキュメントを参照してください。
-
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result)注 :
AppSyncTutorial-Postテーブルでのデータのシェイプは GraphQL でのPost型のシェイプと厳密に一致しているため、このレスポンスマッピングテンプレートは結果をそのまま渡すだけです。また、このチュートリアルのすべての例では、これと同じレスポンスマッピングテンプレートだけを使用しているため、作成するファイルはこの 1 つだけです。 -
[保存] を選択します。
ポストを追加する API の呼び出し
これでリゾルバーがセットアップされたので、 AWS AppSync は着信addPostミューテーションを DynamoDB PutItem オペレーションに変換できます。ユーザーはミューテーションを実行してテーブルに何かを入れることができるようになりました。
-
[クエリ] タブを選択します。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。
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 } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
新しく作成されたポストの結果が、クエリペインの右側にある結果ペインに表示されます。これは次のように表示されます。
{ "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 } } }
何が起こったのかを以下に説明します。
-
AWS AppSync は
addPostミューテーションリクエストを受信しました。 -
AWS AppSync はリクエストとリクエストマッピングテンプレートを受け取り、リクエストマッピングドキュメントを生成しました。そのドキュメントは次のようになっていました。
{ "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : { "S" : "123" } }, "attributeValues" : { "author": { "S" : "AUTHORNAME" }, "title": { "S" : "Our first post!" }, "content": { "S" : "This is our first post." }, "url": { "S" : "https://aws.amazon.com/appsync/" }, "ups" : { "N" : 1 }, "downs" : { "N" : 0 }, "version" : { "N" : 1 } } } -
AWS AppSync は、リクエストマッピングドキュメントを使用して DynamoDB
PutItemリクエストを生成して実行しました。 -
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 } -
そのデータは、レスポンスマッピングドキュメントを介して変更されずに渡されました。
-
新しく作成されたオブジェクトが GraphQL レスポンスで返されました。
getPost リゾルバー (DynamoDB GetItem) のセットアップ
これで、AppSyncTutorial-Post DynamoDB テーブルにデータを追加できるようになりました。次は、AppSyncTutorial-Post テーブルからデータを取得できるように、getPost クエリを設定する必要があります。そのためには、別のリゾルバーを設定します。
-
[Schema (スキーマ)] タブを選択します。
-
右側のデータ型ペインで、Query型のgetPostフィールドを見つけて、[アタッチ] を選択します。
-
[アクション] メニューで [ランタイムの更新] を選択し、[ユニットリゾルバー (VTL のみ)] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "GetItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id) } } -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result) -
[保存] を選択します。
ポストを取得する API の呼び出し
これでリゾルバーが設定され、 AWS AppSync は受信getPostクエリを DynamoDBGetItem オペレーションに変換する方法を知っています。次は、先ほど作成したポストを取得するクエリを実行します。
-
[クエリ] タブを選択します。
-
[Queries] ペインに、次の内容を貼り付けます。
query getPost { getPost(id:123) { id author title content url ups downs version } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
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 } } }
何が起こったのかを以下に説明します。
-
AWS AppSync は
getPostクエリリクエストを受信しました。 -
AWS AppSync はリクエストとリクエストマッピングテンプレートを受け取り、リクエストマッピングドキュメントを生成しました。そのドキュメントは次のようになっていました。
{ "version" : "2017-02-28", "operation" : "GetItem", "key" : { "id" : { "S" : "123" } } } -
AWS AppSync はリクエストマッピングドキュメントを使用して、DynamoDB GetItem リクエストを生成して実行しました。
-
AWS AppSync は
GetItemリクエストの結果を受け取り、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 } -
そのデータは、レスポンスマッピングドキュメントを介して変更されずに渡されました。
-
取得したオブジェクトがレスポンスで返されました。
別の方法として、次の例を指定します。
query getPost { getPost(id:123) { id author title } }
getPost クエリに、id、author および title のみが必要な場合は、DynamoDB から AWS AppSyncへの不要なデータ転送を避けるため、投影式を使用して DynamoDB テーブルから必要な属性のみを指定するようにリクエストマッピングテンプレートを変更できます。例えば、リクエストマッピングテンプレートは以下のスニペットのようになります。
{ "version" : "2017-02-28", "operation" : "GetItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id) }, "projection" : { "expression" : "#author, id, title", "expressionNames" : { "#author" : "author"} } }
updatePost ミューテーション (DynamoDB UpdateItem) の作成
これで、DynamoDB 内の Post オブジェクトを作成および取得できるようになりました。次は、オブジェクトを更新できるように、新しいミューテーションを設定します。そのためには、DynamoDB の UpdateItem オペレーションを使用します。
-
[Schema (スキーマ)] タブを選択します。
-
[スキーマ] ペインの
Mutationタイプを次のように変更して、新しいupdatePostミューテーションを追加します。type Mutation { updatePost( id: ID!, author: String!, title: String!, content: String!, url: String! ): Post addPost( author: String! title: String! content: String! url: String! ): Post! } -
[保存] を選択します。
-
右側のデータ型ペインで、updatePostフィールドに新しく作成されたミューテーション型を見つけて、アタッチを選択します。
-
[アクション] メニューで [ランタイムの更新] を選択し、[ユニットリゾルバー (VTL のみ)] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "SET author = :author, title = :title, content = :content, #url = :url ADD version :one", "expressionNames": { "#url" : "url" }, "expressionValues": { ":author" : $util.dynamodb.toDynamoDBJson($context.arguments.author), ":title" : $util.dynamodb.toDynamoDBJson($context.arguments.title), ":content" : $util.dynamodb.toDynamoDBJson($context.arguments.content), ":url" : $util.dynamodb.toDynamoDBJson($context.arguments.url), ":one" : { "N": 1 } } } }注意: このリゾルバーでは DynamoDB の UpdateItem が使用されていて、そのオペレーションは PutItem オペレーションと大幅に異なります。DynamoDB では、項目全体が書き込まれるのではなく、特定の属性が更新されるようにします。これを行うには、DynamoDB の更新式を使用します。その式自体は、
expressionセクションのupdateフィールドで指定されています。その式では、author、title、content、url の各属性を設定し、versionフィールドを増分しています。使用される値は式自体には記述されていません。この式には、名前がコロンで始まるプレースホルダーがあり、それぞれの値はexpressionValuesフィールドで定義されています。最後に、DynamoDB には、expressionで使用できない予約語があります。例えば、urlは予約語であるため、urlフィールドを更新するには、名前のプレースホルダーをexpressionNamesフィールドで定義できます。UpdateItemリクエストマッピングの詳細については、「UpdateItem」リファレンスドキュメントを参照してください。更新式の記述方法の詳細については、「DynamoDB UpdateExpressions」のドキュメントを参照してください。 -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result)
ポストを更新する API の呼び出し
これでリゾルバーが設定され、 AWS AppSync は着信updateミューテーションを DynamoDBUpdate オペレーションに変換する方法を知っています。ユーザーは、前のステップで書き込んだ項目を更新するミューテーションを実行できるようになりました。
-
[クエリ] タブを選択します。
-
次のミューテーションを [Queries (クエリ)] ペインに貼り付けます。また、
id引数を、前にメモしておいた値に更新する必要があります。mutation updatePost { updatePost( id:"123" author: "A new author" title: "An updated author!" content: "Now with updated content!" url: "https://aws.amazon.com/appsync/" ) { id author title content url ups downs version } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
DynamoDB で更新されたポストが、クエリペインの右側にある結果ペインに表示されます。これは次のように表示されます。
{ "data": { "updatePost": { "id": "123", "author": "A new author", "title": "An updated author!", "content": "Now with updated content!", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 2 } } }
この例では、リクエストマッピングテンプレートが AWS AppSync upsと DynamoDB にそれらのdownsフィールドの操作を要求しなかったため、 フィールドと フィールドは変更されませんでした。また、version フィールドが 1 ずつ増加します。これは、version フィールドに 1 を追加するように AWS AppSync と DynamoDB に指示しているためです。
updatePost リゾルバー (DynamoDB UpdateItem) の変更
updatePost ミューテーションの手始めとしてはこれで十分ですが、次の 2 つの主な問題があります。
-
1 つのフィールドだけを更新する場合でも、すべてのフィールドを更新する必要があります。
-
2 人のユーザーがこのオブジェクトを変更すると、情報が失われる可能性があります。
これらの問題に対処するために、リクエストで指定された引数のみを変更し、UpdateItem オペレーションに条件を追加するように、updatePost ミューテーションを修正します。
-
[Schema (スキーマ)] タブを選択します。
-
[Schema (スキーマ)] ペインで
Mutation型のupdatePostフィールドを変更して、author、title、content、urlの各引数から感嘆符を除去し、idフィールドが元のままになるようにします。これにより、それらの引数が省略可能になります。また、新しい必須のexpectedVersion引数を追加します。type Mutation { updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String! title: String! content: String! url: String! ): Post! } -
[保存] を選択します。
-
右側の [Data types (データ型)] ペインで、ミューテーション型の updatePost フィールドを見つけます。
-
PostDynamoDBTable を選択し、既存リゾルバーを開きます。
-
[Configure the request mapping template (リクエストマッピングテンプレートの設定)] にあるリクエストマッピングテンプレートを次のように変更します。
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, ## Set up some space to keep track of things you're updating ** #set( $expNames = {} ) #set( $expValues = {} ) #set( $expSet = {} ) #set( $expAdd = {} ) #set( $expRemove = [] ) ## Increment "version" by 1 ** $!{expAdd.put("version", ":one")} $!{expValues.put(":one", { "N" : 1 })} ## Iterate through each argument, skipping "id" and "expectedVersion" ** #foreach( $entry in $context.arguments.entrySet() ) #if( $entry.key != "id" && $entry.key != "expectedVersion" ) #if( (!$entry.value) && ("$!{entry.value}" == "") ) ## If the argument is set to "null", then remove that attribute from the item in DynamoDB ** #set( $discard = ${expRemove.add("#${entry.key}")} ) $!{expNames.put("#${entry.key}", "$entry.key")} #else ## Otherwise set (or update) the attribute on the item in DynamoDB ** $!{expSet.put("#${entry.key}", ":${entry.key}")} $!{expNames.put("#${entry.key}", "$entry.key")} $!{expValues.put(":${entry.key}", { "S" : "${entry.value}" })} #end #end #end ## Start building the update expression, starting with attributes you're going to SET ** #set( $expression = "" ) #if( !${expSet.isEmpty()} ) #set( $expression = "SET" ) #foreach( $entry in $expSet.entrySet() ) #set( $expression = "${expression} ${entry.key} = ${entry.value}" ) #if ( $foreach.hasNext ) #set( $expression = "${expression}," ) #end #end #end ## Continue building the update expression, adding attributes you're going to ADD ** #if( !${expAdd.isEmpty()} ) #set( $expression = "${expression} ADD" ) #foreach( $entry in $expAdd.entrySet() ) #set( $expression = "${expression} ${entry.key} ${entry.value}" ) #if ( $foreach.hasNext ) #set( $expression = "${expression}," ) #end #end #end ## Continue building the update expression, adding attributes you're going to REMOVE ** #if( !${expRemove.isEmpty()} ) #set( $expression = "${expression} REMOVE" ) #foreach( $entry in $expRemove ) #set( $expression = "${expression} ${entry}" ) #if ( $foreach.hasNext ) #set( $expression = "${expression}," ) #end #end #end ## Finally, write the update expression into the document, along with any expressionNames and expressionValues ** "update" : { "expression" : "${expression}" #if( !${expNames.isEmpty()} ) ,"expressionNames" : $utils.toJson($expNames) #end #if( !${expValues.isEmpty()} ) ,"expressionValues" : $utils.toJson($expValues) #end }, "condition" : { "expression" : "version = :expectedVersion", "expressionValues" : { ":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion) } } } -
[保存] を選択します。
このテンプレートでは、より複雑な例を示します。マッピングテンプレートの力と柔軟性を示しています。すべての引数をループ処理し、id と expectedVersion をスキップしています。引数が何かに設定されている場合、DynamoDB のオブジェクトでその属性を更新するように AWS AppSync と DynamoDB に要求します。属性が null に設定されている場合、 AWS AppSync と DynamoDB にポストオブジェクトからその属性を削除するように要求します。引数が指定されていない場合、その属性は元のままになります。また、version フィールドが増分されます。
また、新しい condition セクションがあります。条件式を使用すると、オペレーションが実行される前に既に DynamoDB にあるオブジェクトの状態に基づいて、リクエストが成功するかどうかを AWS AppSync と DynamoDB に指示できます。この例では、DynamoDB に現在ある項目の version フィールドが expectedVersion 引数と厳密に一致する場合にのみ、UpdateItem リクエストが成功するように指示しています。
条件式の詳細については、「条件式」リファレンスドキュメントを参照してください。
ポストを更新する API の呼び出し
新しいリゾルバーで Post オブジェクトを更新してみましょう。
-
[クエリ] タブを選択します。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。また、
id引数を、前にメモしておいた値に更新する必要があります。mutation updatePost { updatePost( id:123 title: "An empty story" content: null expectedVersion: 2 ) { id author title content url ups downs version } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
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": 3 } } }
このリクエストでは、 AWS AppSync と DynamoDB に titleフィールドと contentフィールドのみを更新するように依頼しました。その他のフィールドは元のままです (増分する version フィールドは除く)。title 属性を新しい値に設定し、ポストから content 属性を削除しています。author、urlups、downs の各フィールドは変更されません。
リクエストはまったく同じままで、このミューテーションをもう一度実行してみます。次のようなレスポンスが表示されます。
{ "data": { "updatePost": null }, "errors": [ { "path": [ "updatePost" ], "data": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 3 }, "errorType": "DynamoDB:ConditionalCheckFailedException", "locations": [ { "line": 2, "column": 3 } ], "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)" } ] }
このリクエストは、条件式が false と評価されるため失敗します。
-
このリクエストを最初に実行したときに、DynamoDB 内のこのポストの
versionフィールドの値は2であり、expectedVersion引数と一致していました。このリクエストは成功し、DynamoDB でversionフィールドが3に増分されました。 -
このリクエストを 2 回目に実行したときに、DynamoDB 内のこのポストの
versionフィールドの値は3であり、expectedVersion引数と一致していませんでした。
このパターンは通常、「楽観的ロック」と呼ばれます。
AWS AppSync DynamoDB リゾルバーの機能の 1 つは、DynamoDB のポストオブジェクトの現在の値を返すことです。そのことは、GraphQL レスポンスの data セクションの errors フィールドで確認できます。アプリケーションでは、この情報を使用して、どのように続行するかを決めることができます。この例では、DynamoDB 内のオブジェクトの version フィールドが 3 に設定されていることを確認できるため、expectedVersion 引数を 3 に更新するだけで、このリクエストが再度成功するようになります。
条件チェックの失敗の処理の詳細については、マッピングテンプレートのリファレンスドキュメントの「条件式」を参照してください。
upvotePost と downvotePost ミューテーション (DynamoDB UpdateItem) の作成
Post 型には、賛成票と反対票を記録できる ups フィールドと downs フィールドがありますが、この API ではそのフィールドに対して何も行えません。ポストに賛成および反対するための、いくつかのミューテーションを追加してみましょう。
-
[Schema (スキーマ)] タブを選択します。
-
[スキーマ] ペインの
Mutationタイプを変更して、新しいupvotePostとdownvotePostミューテーションを次のように追加します。type Mutation { 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! } -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された upvotePost フィールドを見つけて、[アタッチ] を選択します。
-
[アクション] メニューで [ランタイムの更新] を選択し、[ユニットリゾルバー (VTL のみ)] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "ADD ups :plusOne, version :plusOne", "expressionValues" : { ":plusOne" : { "N" : 1 } } } } -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result) -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された
downvotePostフィールドを見つけて、[アタッチ] を選択します。 -
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "ADD downs :plusOne, version :plusOne", "expressionValues" : { ":plusOne" : { "N" : 1 } } } } -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result) -
[保存] を選択します。
ポストに賛成および反対するための API の呼び出し
これで新しいリゾルバーが設定され、 AWS AppSync は受信upvotePostまたはdownvoteミューテーションを DynamoDB UpdateItem オペレーションに変換する方法を知っています。これで、先ほど作成したポストに賛成または反対するミューテーションを実行できるようになりました。
-
[クエリ] タブを選択します。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。また、
id引数を、前にメモしておいた値に更新する必要があります。mutation votePost { upvotePost(id:123) { id author title content url ups downs version } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
そのポストが DynamoDB で更新され、クエリペインの右側にある結果ペインに表示されます。これは次のように表示されます。
{ "data": { "upvotePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 0, "version": 4 } } } -
さらに数回、[Execute query (クエリを実行)] を選択します。このクエリを実行するたびに、
upsフィールドとversionフィールドが 1 つずつ増加することを確認できます。 -
次のようにクエリを変更し、
downvotePostミューテーションを呼び出します。mutation votePost { downvotePost(id:123) { id author title content url ups downs version } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。今度は、このクエリを実行するたびに、
downsフィールドとversionフィールドが 1 つずつ増加することを確認できます。{ "data": { "downvotePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 4, "version": 12 } } }
deletePost リゾルバー (DynamoDB DeletePost) のセットアップ
次は、ポストを削除するミューテーションを設定します。そのためには、DynamoDB の DeleteItem オペレーションを使用します。
-
[Schema (スキーマ)] タブを選択します。
-
[スキーマ] ペインの
Mutationタイプを次のように変更して、新しいdeletePostミューテーションを追加します。type Mutation { 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! }今回は、
expectedVersionフィールドを省略可能にしています。これについては、リクエストマッピングテンプレートを追加するときに説明します。 -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された delete フィールドを見つけて、[アタッチ] を選択します。
-
[アクション] メニューで [ランタイムの更新] を選択し、[ユニットリゾルバー (VTL のみ)] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "DeleteItem", "key": { "id": $util.dynamodb.toDynamoDBJson($context.arguments.id) } #if( $context.arguments.containsKey("expectedVersion") ) ,"condition" : { "expression" : "attribute_not_exists(id) OR version = :expectedVersion", "expressionValues" : { ":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion) } } #end }注 :
expectedVersion引数は省略可能な引数です。呼び出し元がリクエストでexpectedVersion引数を設定していると、項目が既に削除されている場合、または DynamoDB 内のポストのversion属性がexpectedVersionと完全に一致する場合にのみ、DeleteItemリクエストが成功することを許可する条件が、テンプレートによって追加されます。この引数が省略されている場合は、DeleteItemリクエストで条件式が指定されていません。versionの値や項目が DynamoDB に存在するかどうかに関係なく、成功します。 -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result)注意: 項目を削除する場合でも、その項目がまだ削除されていなければ、削除された項目を返すことができます。
-
[保存] を選択します。
DeleteItem リクエストマッピングの詳細については、「DeleteItem」リファレンスドキュメントを参照してください。
ポストを削除する API の呼び出し
これでリゾルバーが設定され、 AWS AppSync は着信deleteミューテーションを DynamoDBDeleteItem オペレーションに変換する方法を知っています。ユーザーはミューテーションを実行してテーブル内の何かを削除できるようになりました。
-
[クエリ] タブを選択します。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。また、
id引数を、前にメモしておいた値に更新する必要があります。mutation deletePost { deletePost(id:123) { id author title content url ups downs version } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
このポストが DynamoDB から削除されます。 AWS AppSync は、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 } } }
この値は、この deletePost 呼び出しによって実際に DynamoDB から項目が削除された場合にのみ返されます。
-
[クエリを実行] を再度選択します。
-
この呼び出しは成功しますが、値は返されません。
{ "data": { "deletePost": null } }
次は、expectedValue を指定して、ポストを削除してみましょう。ただし、これまで使用してきたポストは削除したため、まず新しいポストを作成する必要があります。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。
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 } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
新しく作成されたポストの結果が、クエリペインの右側にある結果ペインに表示されます。新しく作成されたオブジェクトの
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 } } }
次に、expectedVersion に間違った値を入れて、ポストを削除してみましょう。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。また、
id引数を、前にメモしておいた値に更新する必要があります。mutation deletePost { deletePost( id:123 expectedVersion: 9999 ) { id author title content url ups downs version } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
{ "data": { "deletePost": null }, "errors": [ { "path": [ "deletePost" ], "data": { "id": "123", "author": "AUTHORNAME", "title": "Our second post!", "content": "A new post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 }, "errorType": "DynamoDB:ConditionalCheckFailedException", "locations": [ { "line": 2, "column": 3 } ], "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)" } ] }条件式が false と評価されるため、このリクエストは失敗しました。DynamoDB でのそのポストの
versionの値が、expectedValue引数で指定したものと一致していないためです。そのオブジェクトの現在の値が、GraphQL レスポンスのdataセクションのerrorsフィールドで返されます。 -
expectedVersionを訂正して、このリクエストをもう一度試してみます。mutation deletePost { deletePost( id:123 expectedVersion: 1 ) { id author title content url ups downs version } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
今回は、リクエストが成功し、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 } } } -
[クエリを実行] を再度選択します。
-
この呼び出しは成功しますが、そのポストが DynamoDB で既に削除されているため、今回は値が返されません。
{ "data": { "deletePost": null } }
allPost リゾルバー (DynamoDB Scan) のセットアップ
これまでのところ、APIは、見たい各投稿の id がわかっている場合にのみ便利です。テーブル内のすべてのポストを返す新しいリゾルバーを追加してみましょう。
-
[Schema (スキーマ)] タブを選択します。
-
[スキーマ] ペインの
Queryタイプを次のように変更して、新しいallPostクエリを追加します。type Query { allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post } -
新しい
PaginationPosts型を追加します。type PaginatedPosts { posts: [Post!]! nextToken: String } -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された allPost フィールドを見つけて、[アタッチ] を選択します。
-
[アクション] メニューで [ランタイムの更新] を選択し、[ユニットリゾルバー (VTL のみ)] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "Scan" #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": $util.toJson($context.arguments.nextToken) #end }このリゾルバーには、省略可能な 2 つの引数があります。
countでは、1 回の呼び出しで返される項目の最大数を指定し、nextTokenは、次の結果セットを取得するために使用できます (nextTokenの値がどのように生成されるかについては、後で説明します)。 -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
{ "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end }注 : このレスポンスマッピングテンプレートは、これまで他の例で使用したものとは異なります。
allPostクエリの結果はPaginatedPostsであり、ポストのリストとページ分割トークンが含まれています。このオブジェクトの形状は、 AWS AppSync DynamoDB Resolver から返されるものと異なります。投稿のリストは AWS AppSync DynamoDB Resolver の結果itemsで呼び出されますが、postsでは呼び出されますPaginatedPosts。 -
[保存] を選択します。
Scan リクエストマッピングの詳細については、「Scan」リファレンスドキュメントを参照してください。
すべてのポストをスキャンする API の呼び出し
これでリゾルバーが設定され、 AWS AppSync は受信allPostクエリを DynamoDBScan オペレーションに変換する方法を知っています。ユーザーは、テーブルをスキャンしてすべてのポストを取得できるようになりました。
ただし、これまで使用してきたデータはすべて削除したため、これを試す前にテーブルにデータを入力しておく必要があります。
-
[クエリ] タブを選択します。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。
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 } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
では、テーブルをスキャンして、一度に 5 個の結果を返しましょう。
-
以下のクエリを [クエリ] ペインに貼り付けます。
query allPost { allPost(count: 5) { posts { id title } nextToken } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
最初の 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": "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnRkJEdXdUK09hcnovRGhNTGxLTGdMUEFBQUI1akNDQWVJR0NTcUdTSWIzRFFFSEJxQ0NBZE13Z2dIUEFnRUFNSUlCeUFZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF6ajFodkhKU1paT1pncTRaUUNBUkNBZ2dHWnJiR1dQWGxkMDB1N0xEdGY4Z2JsbktzRjRua1VCcks3TFJLcjZBTFRMeGFwVGJZMDRqOTdKVFQyYVRwSzdzbVdtNlhWWFVCTnFIOThZTzBWZHVkdDI2RlkxMHRqMDJ2QTlyNWJTUWpTbWh6NE5UclhUMG9KZWJSQ2JJbXBlaDRSVlg0Tis0WTVCN1IwNmJQWWQzOVhsbTlUTjBkZkFYMVErVCthaXZoNE5jMk50RitxVmU3SlJ5WmpzMEFkSGduM3FWd2VrOW5oeFVVd3JlK1loUks5QkRzemdiMDlmZmFPVXpzaFZ4cVJRbC93RURlOTcrRmVJdXZNby9NZ1F6dUdNbFRyalpNR3FuYzZBRnhwa0VlZTFtR0FwVDFISElUZlluakptYklmMGUzUmcxbVlnVHVSbDh4S0trNmR0QVoraEhLVDhuNUI3VnF4bHRtSnlNUXBrZGl6KzkyL3VzNDl4OWhrMnVxSW01ZFFwMjRLNnF0dm9ZK1BpdERuQTc5djhzb0grVytYT3VuQ2NVVDY4TVZ1Wk5KYkRuSEFSSEVlaTlVNVBTelU5RGZ6d2pPdmhqWDNJMWhwdWUrWi83MDVHVjlPQUxSTGlwZWZPeTFOZFhwZTdHRDZnQW00bUJUK2c1eC9Ec3ZDbWVnSDFDVXRTdHVuU1ZFa2JpZytQRC9oMUwyRTNqSHhVQldaa28yU256WUc0cG0vV1RSWkFVZHZuQT09In0=" } } }
5 つの結果と nextToken を取得しました。このトークンを使用して、次の結果セットを取得できます。
-
前回の結果セットからの
allPostを含めるように、nextTokenクエリを更新します。query allPost { allPost( count: 5 nextToken: "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnRlluNktJRWl6V0ZlR3hJOVJkaStrZUFBQUI1akNDQWVJR0NTcUdTSWIzRFFFSEJxQ0NBZE13Z2dIUEFnRUFNSUlCeUFZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5cW8yUGFSZThnalFpemRCTUNBUkNBZ2dHWk1JODhUNzhIOFVUZGtpdFM2ZFluSWRyVDg4c2lkN1RjZzB2d1k3VGJTTWpSQ2U3WjY3TkUvU2I1dWNETUdDMmdmMHErSGJSL0pteGRzYzVEYnE1K3BmWEtBdU5jSENJdWNIUkJ0UHBPWVdWdCtsS2U5L1pNcWdocXhrem1RaXI1YnIvQkt6dU5hZmJCdE93NmtoM2Jna1BKM0RjWWhpMFBGbmhMVGg4TUVGSjBCcXg3RTlHR1V5N0tUS0JLZlV3RjFQZ0JRREdrNzFYQnFMK2R1S2IrVGtZZzVYMjFrc3NyQmFVTmNXZmhTeXE0ZUJHSWhqZWQ5c3VKWjBSSTc2ZnVQdlZkR3FLNENjQmxHYXhpekZnK2pKK1FneEU1SXduRTNYYU5TR0I4QUpmamR2bU1wbUk1SEdvWjlMUUswclczbG14RDRtMlBsaTNLaEVlcm9pem5zcmdINFpvcXIrN2ltRDN3QkJNd3BLbGQzNjV5Nnc4ZnMrK2FnbTFVOUlKOFFrOGd2bEgySHFROHZrZXBrMWlLdWRIQ25LaS9USnBlMk9JeEVPazVnRFlzRTRUU09HUlVJTkxYY2MvdW1WVEpBMUthV2hWTlAvdjNlSnlZQUszbWV6N2h5WHVXZ1BkTVBNWERQdTdjVnVRa3EwK3NhbGZOd2wvSUx4bHNyNDVwTEhuVFpyRWZvVlV1bXZ5S2VKY1RUU1lET05hM1NwWEd2UT09In0=" ) { posts { id author } nextToken } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
残りの 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」リゾルバー (DynamoDB クエリ) のセットアップ
DynamoDB ですべてのポストをスキャンだけでなく、特定の作成者が作成したポストを取得するクエリを DynamoDB に対して実行することもできます。前の手順で作成した DynamoDB テーブルには、既に author-index という GlobalSecondaryIndex があるため、DynamoDB の Query オペレーションでそれを使用して、特定の作成者が作成したすべてのポストを取得できます
-
[Schema (スキーマ)] タブを選択します。
-
[スキーマ] ペインの
Queryタイプを次のように変更して、新しいallPostsByAuthorクエリを追加します。type Query { allPostsByAuthor(author: String!, count: Int, nextToken: String): PaginatedPosts! allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }注 : このクエリでは、
allPostクエリで使用したのと同じPaginatedPosts型を使用しています。 -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された allPostsByAuthor フィールドを見つけて、[アタッチ] を選択します。
-
[アクション] メニューで [ランタイムの更新] を選択し、[ユニットリゾルバー (VTL のみ)] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "Query", "index" : "author-index", "query" : { "expression": "author = :author", "expressionValues" : { ":author" : $util.dynamodb.toDynamoDBJson($context.arguments.author) } } #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": "${context.arguments.nextToken}" #end }allPostリゾルバーと同様に、このリゾルバーには、省略可能な 2 つの引数があります。countでは、1 回の呼び出しで返される項目の最大数を指定し、nextTokenは、次の結果セットを取得するために使用できます (nextTokenの値は前回の呼び出しから取得できます)。 -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
{ "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end }注 : これは、
allPostリゾルバーで使用したのと同じレスポンスマッピングテンプレートです。 -
[保存] を選択します。
Query リクエストマッピングの詳細については、「クエリ」リファレンスドキュメントを参照してください。
特定の作成者によるすべてのポストをクエリする API の呼び出し
これでリゾルバーが設定され、 AWS AppSync は受信allPostsByAuthorミューテーションをauthor-indexインデックスに対する DynamoDBQuery オペレーションに変換する方法を知っています。ユーザーは、テーブルをクエリして、特定の作成者によるポストをすべて取得できます。
ただし、これまで使用していたポストはすべて同じ作成者だったため、それを行う前に、テーブルにポストを追加しておきましょう。
-
[クエリ] タブを選択します。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。
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 } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
では、Nadia が作成したすべてのポストを返すクエリを実行しましょう。
-
以下のクエリを [クエリ] ペインに貼り付けます。
query allPostsByAuthor { allPostsByAuthor(author: "Nadia") { posts { id title } nextToken } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
Nadiaが作成したすべてのポストが、クエリペインの右側にある結果ペインに表示されます。これは次のように表示されます。{ "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you know...?" } ], "nextToken": null } } }
Query でのページ分割は Scan とまったく同じように動作します。例えば、AUTHORNAME によるすべてのポストを検索して、一度に 5 個ずつ取得します。
-
以下のクエリを [クエリ] ペインに貼り付けます。
query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" count: 5 ) { posts { id title } nextToken } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
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": "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnSExqRnVhVUR3ZUhEZ2QzNGJ2QlFuY0FBQUNqekNDQW9zR0NTcUdTSWIzRFFFSEJxQ0NBbnd3Z2dKNEFnRUFNSUlDY1FZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5Qkg4Yk1obW9LVEFTZHM3SUNBUkNBZ2dKQ3dISzZKNlJuN3pyYUVKY1pWNWxhSkNtZW1KZ0F5N1dhZkc2UEdTNHpNQzJycTkwZHFJTFV6Z25wck9Gd3pMS3VOQ2JvUXc3VDI5eCtnVExIbGg4S3BqbzB1YjZHQ3FwcDhvNDVmMG9JbDlmdS9JdjNXcFNNSXFKTXZ1MEVGVWs1VzJQaW5jZGlUaVRtZFdYWlU1bkV2NkgyRFBRQWZYYlNnSmlHSHFLbmJZTUZZM0FTdmRIL0hQaVZBb1RCMk1YZkg0eGJOVTdEbjZtRFNhb2QwbzdHZHJEWDNtODQ1UXBQUVNyUFhHemY0WDkyajhIdlBCSWE4Smcrb0RxbHozUVQ5N2FXUXdYWWU2S0h4emI1ejRITXdEdXEyRDRkYzhoMi9CbW10MzRMelVGUVIyaExSZGRaZ0xkdzF5cHJZdFZwY3dEc1d4UURBTzdOcjV2ZEp4VVR2TVhmODBRSnp1REhXREpTVlJLdDJwWmlpaXhXeGRwRmNod1BzQ3d2aVBqMGwrcWFFWU1jMXNQbENkVkFGem43VXJrSThWbS8wWHlwR2xZb3BSL2FkV0xVekgrbGMrYno1ZEM2SnVLVXdtY1EyRXlZeDZiS0Izbi9YdUViWGdFeU5PMWZTdE1rRlhyWmpvMVpzdlYyUFRjMzMrdEs0ZDhkNkZrdjh5VVR6WHhJRkxIaVNsOUx6VVdtT3BCaWhrTFBCT09jcXkyOHh1UmkzOEM3UFRqMmN6c3RkOUo1VUY0azBJdUdEbVZzM2xjdWg1SEJjYThIeXM2aEpvOG1HbFpMNWN6R2s5bi8vRE1EbDY3RlJraG5QNFNhSDBpZGI5VFEvMERLeFRBTUdhcWpPaEl5ekVqd2ZDQVJleFdlbldyOGlPVkhScDhGM25WZVdvbFRGK002N0xpdi9XNGJXdDk0VEg3b0laUU5lYmZYKzVOKy9Td25Hb1dyMTlWK0pEb2lIRVFLZ1cwMWVuYjZKUXo5Slh2Tm95ZzF3RnJPVmxGc2xwNlRHa1BlN2Rnd2IrWT0ifQ==" } } } -
次のように、
nextToken引数を、前回のクエリで返された値に更新します。query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" count: 5 nextToken: "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnSExqRnVhVUR3ZUhEZ2QzNGJ2QlFuY0FBQUNqekNDQW9zR0NTcUdTSWIzRFFFSEJxQ0NBbnd3Z2dKNEFnRUFNSUlDY1FZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5Qkg4Yk1obW9LVEFTZHM3SUNBUkNBZ2dKQ3dISzZKNlJuN3pyYUVKY1pWNWxhSkNtZW1KZ0F5N1dhZkc2UEdTNHpNQzJycTkwZHFJTFV6Z25wck9Gd3pMS3VOQ2JvUXc3VDI5eCtnVExIbGg4S3BqbzB1YjZHQ3FwcDhvNDVmMG9JbDlmdS9JdjNXcFNNSXFKTXZ1MEVGVWs1VzJQaW5jZGlUaVRtZFdYWlU1bkV2NkgyRFBRQWZYYlNnSmlHSHFLbmJZTUZZM0FTdmRIL0hQaVZBb1RCMk1YZkg0eGJOVTdEbjZtRFNhb2QwbzdHZHJEWDNtODQ1UXBQUVNyUFhHemY0WDkyajhIdlBCSWE4Smcrb0RxbHozUVQ5N2FXUXdYWWU2S0h4emI1ejRITXdEdXEyRDRkYzhoMi9CbW10MzRMelVGUVIyaExSZGRaZ0xkdzF5cHJZdFZwY3dEc1d4UURBTzdOcjV2ZEp4VVR2TVhmODBRSnp1REhXREpTVlJLdDJwWmlpaXhXeGRwRmNod1BzQ3d2aVBqMGwrcWFFWU1jMXNQbENkVkFGem43VXJrSThWbS8wWHlwR2xZb3BSL2FkV0xVekgrbGMrYno1ZEM2SnVLVXdtY1EyRXlZeDZiS0Izbi9YdUViWGdFeU5PMWZTdE1rRlhyWmpvMVpzdlYyUFRjMzMrdEs0ZDhkNkZrdjh5VVR6WHhJRkxIaVNsOUx6VVdtT3BCaWhrTFBCT09jcXkyOHh1UmkzOEM3UFRqMmN6c3RkOUo1VUY0azBJdUdEbVZzM2xjdWg1SEJjYThIeXM2aEpvOG1HbFpMNWN6R2s5bi8vRE1EbDY3RlJraG5QNFNhSDBpZGI5VFEvMERLeFRBTUdhcWpPaEl5ekVqd2ZDQVJleFdlbldyOGlPVkhScDhGM25WZVdvbFRGK002N0xpdi9XNGJXdDk0VEg3b0laUU5lYmZYKzVOKy9Td25Hb1dyMTlWK0pEb2lIRVFLZ1cwMWVuYjZKUXo5Slh2Tm95ZzF3RnJPVmxGc2xwNlRHa1BlN2Rnd2IrWT0ifQ==" ) { posts { id title } nextToken } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
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 } } }
セット型の使用
ここまでの Post 型は、フラットなキーと値のオブジェクトでした。セット、リスト、マップなど、 AWS AppSyncDynamoDB リゾルバーを使用して複雑なオブジェクトをモデル化することもできます。
Post 型を更新して、タグを含めましょう。1 つのポストには、DynamoDB に文字列として保存されているタグを 0 個以上付けることができます。タグを追加および削除するミューテーションと、特定のタグが付いているポストをスキャンする新しいクエリもセットアップします。
-
[Schema (スキーマ)] タブを選択します。
-
[スキーマ] ペインの
Postタイプを次のように変更して、新しいtagsフィールドを追加します。type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! tags: [String!] } -
[スキーマ] ペインの
Queryタイプを次のように変更して、新しいallPostsByTagクエリを追加します。type Query { allPostsByTag(tag: String!, count: Int, nextToken: String): PaginatedPosts! allPostsByAuthor(author: String!, count: Int, nextToken: String): PaginatedPosts! allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post } -
[スキーマ] ペインの
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! } -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された allPostsByTag フィールドを見つけて、[アタッチ] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "Scan", "filter": { "expression": "contains (tags, :tag)", "expressionValues": { ":tag": $util.dynamodb.toDynamoDBJson($context.arguments.tag) } } #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": $util.toJson($context.arguments.nextToken) #end } -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
{ "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end } -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された addTag フィールドを見つけて、[アタッチ] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "ADD tags :tags, version :plusOne", "expressionValues" : { ":tags" : { "SS": [ $util.toJson($context.arguments.tag) ] }, ":plusOne" : { "N" : 1 } } } } -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result) -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された removeTag フィールドを見つけて、[アタッチ] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "DELETE tags :tags ADD version :plusOne", "expressionValues" : { ":tags" : { "SS": [ $util.toJson($context.arguments.tag) ] }, ":plusOne" : { "N" : 1 } } } } -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result) -
[保存] を選択します。
タグを操作する API の呼び出し
リゾルバーをセットアップしたので、 AWS AppSync は受信 addTag、、removeTagおよび allPostsByTagリクエストを DynamoDBUpdateItem および Scanオペレーションに変換する方法を理解しています。
それを試すには、前のステップで作成したポストのいずれかを選択します。例えば、Nadia が作成したポストを使用しましょう。
-
[クエリ] タブを選択します。
-
以下のクエリを [クエリ] ペインに貼り付けます。
query allPostsByAuthor { allPostsByAuthor( author: "Nadia" ) { posts { id title } nextToken } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
Nadia のすべてのポストが、クエリペインの右側にある結果ペインに表示されます。これは次のように表示されます。
{ "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you known...?" } ], "nextToken": null } } } -
タイトルが「
"The cutest dog in the world"」のポストを使用しましょう。idは後で使用するため書き留めておきます。
では、dog タグを追加してみましょう。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。また、
id引数を、前にメモしておいた値に更新する必要があります。mutation addTag { addTag(id:10 tag: "dog") { id title tags } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
ポストが新しいタグで更新されています。
{ "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }
次のようにタグを追加できます。
-
puppyに変更するように、tag引数を更新します。mutation addTag { addTag(id:10 tag: "puppy") { id title tags } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
ポストが新しいタグで更新されています。
{ "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } } }
タグを削除することもできます。
-
以下のミューテーションを [クエリ] ペインに貼り付けます。また、
id引数を、前にメモしておいた値に更新する必要があります。mutation removeTag { removeTag(id:10 tag: "puppy") { id title tags } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
ポストが更新され、
puppyタグが削除されています。{ "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }
タグが付いているすべてのポストを検索することもできます。
-
以下のクエリを [クエリ] ペインに貼り付けます。
query allPostsByTag { allPostsByTag(tag: "dog") { posts { id title tags } nextToken } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
次のように
dogタグが付いているすべての投稿が返されます。{ "data": { "allPostsByTag": { "posts": [ { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } ], "nextToken": null } } }
リスト型とマップ型の使用
DynamoDB のセット型を使用するだけでなく、DynamoDB のリスト型やマップ型を使用して、複雑なデータを単一のオブジェクトにモデル化することもできます。
ポストにコメントを追加する機能を追加しましょう。これは、DynamoDB 内の Post オブジェクトで、マップ型オブジェクトのリスト型としてモデル化されます。
注 : 実際のアプリケーションでは、独自のテーブル内のコメントをモデル化します。このチュートリアルでは、Post テーブルにコメントを追加しているだけです。
-
[Schema (スキーマ)] タブを選択します。
-
[Schema (スキーマ)] ペインで、次のように新しい
Comment型を追加します。type Comment { author: String! comment: String! } -
[スキーマ] ペインの
Postタイプを次のように変更して、新しいcommentsフィールドを追加します。type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! tags: [String!] comments: [Comment!] } -
[スキーマ] ペインの
Mutationタイプを次のように変更して、新しいaddCommentミューテーションを追加します。type Mutation { addComment(id: ID!, author: String!, comment: String!): Post 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! } -
[保存] を選択します。
-
右側のデータ型ペインで、ミューテーション型の新しく作成された addComment フィールドを見つけて、[アタッチ] を選択します。
-
[データソース名] で、[PostDynamoDBTable] を選択します。
-
以下のコードを [リクエストマッピングテンプレートの設定] に貼り付けます。
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "SET comments = list_append(if_not_exists(comments, :emptyList), :newComment) ADD version :plusOne", "expressionValues" : { ":emptyList": { "L" : [] }, ":newComment" : { "L" : [ { "M": { "author": $util.dynamodb.toDynamoDBJson($context.arguments.author), "comment": $util.dynamodb.toDynamoDBJson($context.arguments.comment) } } ] }, ":plusOne" : $util.dynamodb.toDynamoDBJson(1) } } }この更新式によって、新しいコメントが含まれているリストが、既存の
commentsリストに追加されます。リストがまだ存在しない場合は作成されます。 -
以下のコードを [レスポンスマッピングテンプレートの設定] に貼り付けます。
$utils.toJson($context.result) -
[保存] を選択します。
コメントを追加する API の呼び出し
リゾルバーをセットアップしたので、 AWS AppSync は受信addCommentリクエストを DynamoDBUpdateItem オペレーションに変換する方法を理解しています。
タグを追加したのと同じポストにコメントを追加して、試してみましょう。
-
[クエリ] タブを選択します。
-
以下のクエリを [クエリ] ペインに貼り付けます。
mutation addComment { addComment( id:10 author: "Steve" comment: "Such a cute dog." ) { id comments { author comment } } } -
[Execute query (クエリを実行)] (オレンジ色の再生ボタン) を選択します。
-
Nadia のすべてのポストが、クエリペインの右側にある結果ペインに表示されます。これは次のように表示されます。
{ "data": { "addComment": { "id": "10", "comments": [ { "author": "Steve", "comment": "Such a cute dog." } ] } } }
このリクエストを複数回実行すると、複数のコメントがリストに追加されます。
結論
このチュートリアルでは、 AWS AppSync と GraphQL を使用して DynamoDB 内のポストオブジェクトを操作できる API を構築しました。詳細については、「リゾルバーのマッピングテンプレートリファレンス」を参照してください。
クリーンアップするには、AppSync GraphQL API をコンソールから削除します。
このチュートリアル用に作成した DynamoDB テーブルと IAM ロールを削除するには、以下を実行してAWSAppSyncTutorialForAmazonDynamoDBスタックを削除するか、 AWS CloudFormation コンソールにアクセスしてスタックを削除します。
aws cloudformation delete-stack \ --stack-name AWSAppSyncTutorialForAmazonDynamoDB