DynamoDB JavaScript リゾルバーを使用したシンプルなポストアプリケーションの作成 - AWS AppSync

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

DynamoDB JavaScript リゾルバーを使用したシンプルなポストアプリケーションの作成

このチュートリアルでは、Amazon DynamoDB テーブルを にインポート AWS AppSync して接続し、独自のアプリケーションで活用できる JavaScript パイプラインリゾルバーAPIを使用して、フル機能の GraphQL を構築します。

AWS AppSync コンソールを使用して Amazon DynamoDB リソースをプロビジョニングし、リゾルバーを作成し、データソースに接続します。また、GraphQL ステートメントを使用して Amazon DynamoDB データベースへの読み取りと書き込みを行うことができ、リアルタイムデータをサブスクライブできます。

GraphQL ステートメントが Amazon DynamoDB オペレーションに変換され、レスポンスが GraphQL に変換されるように、特定のステップを完了しておく必要があります。このチュートリアルでは、いくつかの実際のシナリオおよびデータアクセスパターンを使用して、その設定手順の概要を示します。

GraphQL の作成 API

APIで GraphQL を作成するには AWS AppSync

  1. AppSync コンソールを開き、 の作成 APIを選択します。

  2. [最初から設計] を選択し、[次へ] を選択します。

  3. に名前を付けAPIPostTutorialAPI次へ を選択します。残りのオプションはデフォルト設定値のまま、レビューページに移動し、Create を選択します。

AWS AppSync コンソールは新しい GraphQL を作成しますAPI。ディタルトでは、APIキー認証モードを使用します。コンソールを使用して、残りの GraphQL をセットアップAPIし、このチュートリアルの残りの部分に対してクエリを実行できます。

基本的な投稿の定義 API

GraphQL が完成したらAPI、投稿データの基本作成、取得、削除を許可する基本スキーマを設定できます。

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

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

  2. 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! }
  3. [Save Schema] を選択します。

Amazon DynamoDB テーブルのセットアップ

AWS AppSync コンソールは、独自の AWS リソースを Amazon DynamoDB テーブルに保存するために必要なリソースをプロビジョニングするのに役立ちます。このステップでは、投稿を保存する Amazon DynamoDB テーブルを作成します。また、後で使用するセカンダリインデックスも設定します。

Amazon DynamoDB テーブルを作成するには

  1. [スキーマ] ページで、[リソースを作成] を選択します。

  2. [既存のタイプを使用] を選択し、Post タイプを選択します。

  3. [セカンダリインデックス] セクションで、[インデックスを追加] を選択します。

  4. インデックス author-index の名前

  5. Primary keyauthor に、Sort キーを None に設定します。

  6. GraphQL の自動生成を無効にします。この例では、リゾルバーを自分で作成します。

  7. [Create] (作成) を選択します。

これで、PostTable という新しいデータソースができました。サイドタブの [データソース] にアクセスすると確認できます。このデータソースを使用して、クエリとミューテーションを Amazon DynamoDB テーブルにリンクします。

addPost リゾルバーの設定 (Amazon DynamoDB PutItem)

これで AWS AppSync 、Amazon DynamoDB テーブルを認識できたので、リゾルバーを定義することで、個々のクエリやミューテーションにリンクできます。最初に作成するリゾルバーは、 を使用するaddPostパイプラインリゾルバーです。これにより JavaScript、Amazon DynamoDB テーブルに投稿を作成できます。パイプラインリゾルバーには以下のコンポーネントがあります。

  • リゾルバーをアタッチする、GraphQL スキーマ内の場所。この例では、createPost 型の Mutation フィールドにリゾルバーをセットアップしています。このリゾルバーは、呼び出し元がミューテーション { addPost(...){...} } を呼び出したときに呼び出されます。

  • このリゾルバーで使用するデータソース。この例では、post-table-for-tutorial DynamoDB テーブルにエントリを追加できるように、前に定義した データソースを使用します。

  • リクエストハンドラー。リクエストハンドラーは、発信者からの受信リクエストを処理し、DynamoDB に対して実行する の手順に変換 AWS AppSync する関数です。 DynamoDB

  • レスポンスハンドラー。レスポンスハンドラーの仕事は、DynamoDB からのレスポンスに対応して、それを GraphQL で想定されているものに変換し直すことです。これは、DynamoDB でのデータのシェイプが GraphQL での Post 型と異なる場合に便利です。ただし、この例では、両方のシェイプが同じであるため、データをそのまま渡します。

リゾルバーをセットアップするには

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

  2. リゾルバー ペインで、Mutation 型の下にある addPost フィールドを探し、「アタッチ」を選択します。

  3. データソースを選択し、[作成] を選択します。

  4. コードエディターで、コードを次のスニペットに置き換えます。

    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 }
  5. [Save] を選択します。

注記

このコードでは、DynamoDB リクエストを簡単に作成できる DynamoDB モジュール utils を使用します。

AWS AppSync には、 という名前の自動 ID 生成用のユーティリティが付属しています。これはutil.autoId()、新しい投稿の ID を生成するために使用されます。ID を指定しないと、ユーティリティによって自動的に ID が生成されます。

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

で使用できるユーティリティの詳細については JavaScript、JavaScript「リゾルバーと関数のランタイム機能」を参照してください。

API を呼び出して投稿を追加する

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

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

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

  2. 以下のミューテーションを [クエリ] ペインに追加します。

    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 } }
  3. [実行] (オレンジ色の再生ボタン) を選択し、[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ミューテーションリクエストを受信しました。

  2. 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/' } } }
  3. AWS AppSync はこの値を使用して Amazon DynamoDB PutItemリクエストを生成および実行します。

  4. 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 }
  5. レスポンスハンドラーは結果をすぐに返します (return ctx.result)。

  6. 最終結果は GraphQL のレスポンスに表示されます。

getPost リゾルバーのセットアップ (Amazon DynamoDB GetItem)

これで、 Amazon DynamoDB テーブルにデータを追加できるようになりました。次は、からデータを取得できるように、getPost クエリを設定する必要があります。そのためには、別のリゾルバーを設定します。

リソースを追加するには、次の手順に従います。

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

  2. 右側の [リゾルバー] ペインで、Query タイプの getPost フィールドを見つけて [アタッチ] を選択します。

  3. データソースを選択し、[作成] を選択します。

  4. コードエディタで、コードを次のスニペットに置き換えます。

    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
  5. リゾルバーを保存します。

注記

このリゾルバーでは、レスポンスハンドラーに矢印関数式を使用しています。

API を呼び出して投稿を取得する

これでリゾルバーが設定され、受信getPostクエリを Amazon DynamoDB GetItemオペレーションに変換する AWS AppSync 方法について説明します。次は、先ほど作成したポストを取得するクエリを実行します。

クエリを実行するには

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

  2. クエリ ペインで次のコードを追加し、投稿を作成した後にコピーした ID を使用します。

    query getPost { getPost(id: "123") { id author title content url ups downs version } }
  3. [実行] (オレンジ色の再生ボタン) を選択し、[getPost] を選択します。新しく作成されたポストの結果が、クエリペインの右側にある結果ペインに表示されます。

  4. 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 クエリが idauthortitle のみを必要とする場合は、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 と を使用して 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)

これで、Amazon DynamoDB 内の Post オブジェクトを作成および取得できるようになりました。次は、オブジェクトを更新できるように、新しいミューテーションを設定します。すべてのフィールドを指定する必要がある addPost ミューテーションと比較すると、このミューテーションでは変更するフィールドのみを指定できます。また、変更するバージョンを指定できる新しい expectedVersion 引数が導入されました。オブジェクトの最新バージョンを変更していることを確認する条件を設定します。そのためには、UpdateItem Amazon DynamoDB operation.sc を使用します。

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

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

  2. [スキーマ] ペインの 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! }
  3. [Save Schema] を選択します。

  4. 右側の [リゾルバー] ペインで、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;
  5. 加えた変更を保存します。

このリゾルバーは ddb.update を使用して Amazon DynamoDB の作成 UpdateItem を行います。Amazon DynamoDB では、項目全体が書き込まれるのではなく、特定の属性が更新されるようにします。これを行うには、Amazon DynamoDB の更新式を使用します。

ddb.update 関数はキーと更新オブジェクトを引数として取得します。次に、入力された引数の値をチェックします。値がnullに設定されたら、DynamoDB remove オペレーションを使用して、値を DynamoDB 項目から削除する必要があることを通知します。

また、新しい condition セクションがあります。条件式を使用すると、 AWS AppSync および Amazon DynamoDB に対して、オペレーションが実行される前に、Amazon DynamoDB に既に存在するオブジェクトの状態に基づいてリクエストが成功するかどうかを指示できます。この例では、Amazon DynamoDB に現在ある項目の version フィールドが expectedVersion 引数と厳密に一致する場合にのみ、UpdateItem リクエストが成功するように指示しています。項目が更新されたら、version の値をインクリメントする必要があります。これは操作機能 increment を使えば簡単に行えます。

条件式の詳細については、「条件式リファレンス」ドキュメントを参照してください。

UpdateItem リクエストの詳細については、 UpdateItemドキュメントと DynamoDB モジュールドキュメントを参照してください。

更新式を記述する方法の詳細については、DynamoDB UpdateExpressionsドキュメントを参照してください。

API を呼び出して投稿を更新する

新しいリゾルバーで Post オブジェクトを更新してみましょう。

オブジェクトを更新するには

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

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

    mutation updatePost { updatePost( id:123 title: "An empty story" content: null expectedVersion: 1 ) { id author title content url ups downs version } }
  3. [実行] (オレンジ色の再生ボタン) を選択し、[updatePost] を選択します。

  4. 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 属性を削除しています。authorurlupsdowns の各フィールドは変更されません。リクエストはまったく同じままで、このミューテーションをもう一度実行してみます。次のようなレスポンスが表示されます。

{ "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 に増分されました。

  2. このリクエストを 2 回目に実行したときに、Amazon DynamoDB 内のこのポストの version フィールドの値は 2 であり、expectedVersion 引数と一致していませんでした。

このパターンは通常、「楽観的ロック」と呼ばれます。

投票ミューテーションを作成する (Amazon DynamoDB UpdateItem)

Post タイプには、賛成票と反対票を記録できるようにする upsdowns フィールドが含まれます。ただし、現時点では、 APIでは何もできません。投稿に賛成および反対するための、いくつかのミューテーションを追加してみましょう。

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

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

  2. [スキーマ] ペインの 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 }
  3. [Save Schema] を選択します。

  4. 右側の [リゾルバー] ペインで、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;
  5. 加えた変更を保存します。

API を呼び出して投稿をアップボットまたはダウンボットする

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

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

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

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

    mutation votePost { vote(id:123, direction: UP) { id author title content url ups downs version } }
  3. [実行] (オレンジ色の再生ボタン) を選択し、[votePost] を選択します。

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

  6. クエリを変更して、別の DIRECTION を呼び出してください。

    mutation votePost { vote(id:123, direction: DOWN) { id author title content url ups downs version } }
  7. [実行] (オレンジ色の再生ボタン) を選択し、[votePost] を選択します。

    今度は、このクエリを実行するたびに、downs フィールドと version フィールドが 1 つずつ増加することを確認できます。

deletePost リゾルバーの設定 (Amazon DynamoDB DeleteItem)

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

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

  1. スキーマで、「スキーマ」タブを選択します。

  2. [スキーマ] ペインの 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! }
  3. 今回は、expectedVersion フィールドをオプションにしました。[スキーマを保存] を選択します。

  4. 右側の [リゾルバー] ペインで、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ドキュメントを参照してください。

API を呼び出して投稿を削除する

これでリゾルバーが設定され、着信deleteミューテーションを Amazon DynamoDB DeleteItemオペレーションに変換 AWS AppSync する方法について説明します。ユーザーはミューテーションを実行してテーブル内の何かを削除できるようになりました。

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

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

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

    mutation deletePost { deletePost(id:123) { id author title content url ups downs version } }
  3. [実行] (オレンジ色の再生ボタン) を選択し、[deletePost] を選択します。

  4. この投稿が 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 } } }
  5. この値は、この deletePost 呼び出しによって実際に Amazon DynamoDB から項目が削除された場合にのみ返されます。再度 [実行] を選択します。

  6. この呼び出しは成功しますが、値は返されません。

    { "data": { "deletePost": null } }
  7. 次は、expectedValue を指定して、ポストを削除してみましょう。まず、これまで使用してきたポストは削除したため、まず新しいポストを作成する必要があります。

  8. 以下のミューテーションを [クエリ] ペインに追加します。

    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 } }
  9. [実行] (オレンジ色の再生ボタン) を選択し、[addPost] を選択します。

  10. 新しく作成されたポストの結果が、クエリペインの右側にある結果ペインに表示されます。新しく作成されたオブジェクトの 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 } } }
  11. 次に、 の無効な値でその投稿を削除してみましょうexpectedVersion。以下のミューテーションを [クエリ] ペインに貼り付けます。また、id 引数を、前にメモしておいた値に更新する必要があります。

    mutation deletePost { deletePost( id:123 expectedVersion: 9999 ) { id author title content url ups downs version } }
  12. [実行] (オレンジ色の再生ボタン) を選択し、[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)" } ] }
  13. このリクエストは、条件式が false と評価されるため失敗します。Amazon DynamoDB version の投稿の値が、expectedValue引数で指定された値と一致しません。そのオブジェクトの現在の値が、GraphQL レスポンスの data セクションの errors フィールドで返されます。expectedVersion を訂正して、このリクエストをもう一度試してみます。

    mutation deletePost { deletePost( id:123 expectedVersion: 1 ) { id author title content url ups downs version } }
  14. [実行] (オレンジ色の再生ボタン) を選択し、[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 } } }
  15. 再度 [実行] を選択します。この呼び出しは成功しますが、そのポストが Amazon DynamoDB で既に削除されているため、今回は値が返されません。

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

allPost リゾルバーのセットアップ (Amazon DynamoDB スキャン)

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

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

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

  2. [スキーマ] ペインの Query タイプを次のように変更して、新しい allPost クエリを追加します。

    type Query { allPost(limit: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }
  3. 新しい PaginationPosts 型を追加します。

    type PaginatedPosts { posts: [Post!]! nextToken: String }
  4. [Save Schema] を選択します。

  5. 右側の [リゾルバー] ペインで、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の値がどこから来たのかは後で説明します)。

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

Scan リクエストの詳細については、「Scan」リファレンスドキュメントを参照してください。

を呼び出しAPIてすべての投稿をスキャンする

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

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

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

  2. 以下のミューテーションを [クエリ] ペインに追加します。

    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 } }
  3. [実行] (オレンジ色の再生ボタン) を選択します。

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

    query allPost { allPost(limit: 5) { posts { id title } nextToken } }
  5. [実行] (オレンジ色の再生ボタン) を選択し、[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>" } } }
  6. 5 つの結果と nextToken を取得しました。このトークンを使用して、次の結果セットを取得できます。前回の結果セットからの allPost を含めるように、nextToken クエリを更新します。

    query allPost { allPost( limit: 5 nextToken: "<token>" ) { posts { id author } nextToken } }
  7. [実行] (オレンジ色の再生ボタン) を選択し、[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 } } }

allPostsBy作成者リゾルバーの設定 (Amazon DynamoDB クエリ)

Amazon DynamoDB ですべてのポストをスキャンだけでなく、特定の作成者が作成したポストを取得するクエリを Amazon DynamoDB に対して実行することもできます。前の手順で作成した Amazon DynamoDB テーブルには、既に author-index という GlobalSecondaryIndex があるため、Amazon DynamoDB の Query オペレーションでそれを使用して、特定の作成者が作成したすべてのポストを取得できます

クエリを追加するには

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

  2. [スキーマ] ペインの Query タイプを次のように変更して、新しい allPostsByAuthor クエリを追加します。

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

    このクエリでは、allPost クエリで使用したのと同じ PaginatedPosts 型を使用していることに注意してください。

  3. [Save Schema] を選択します。

  4. 右側のリゾルバーペインで、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の値は前回の呼び出しから取得できます)。

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

Query リクエストの詳細については、「クエリ」リファレンスドキュメントを参照してください。

を呼び出しAPIて、作成者によるすべての投稿をクエリします。

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

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

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

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

  2. 以下のミューテーションを [クエリ] ペインに追加します。

    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 } }
  3. [実行] (オレンジ色の再生ボタン) を選択し、[addPost] を選択します。

  4. では、Nadia が作成したすべてのポストを返すクエリを実行しましょう。以下のクエリをクエリペインに貼り付けます。

    query allPostsByAuthor { allPostsByAuthor(author: "Nadia") { posts { id title } nextToken } }
  5. [実行] (オレンジ色の再生ボタン) を選択し、[allPostsByAuthor] を選択します。Nadia が作成したすべてのポストが、クエリペインの右側にある結果ペインに表示されます。これは次のように表示されます。

    { "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you know...?" } ], "nextToken": null } } }
  6. Query でのページ分割は Scan とまったく同じように動作します。例えば、AUTHORNAME によるすべてのポストを検索して、一度に 5 個ずつ取得します。

  7. 以下のクエリをクエリペインに貼り付けます。

    query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" limit: 5 ) { posts { id title } nextToken } }
  8. [実行] (オレンジ色の再生ボタン) を選択し、[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>" } } }
  9. 次のように、nextToken 引数を、前回のクエリで返された値に更新します。

    query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" limit: 5 nextToken: "<token>" ) { posts { id title } nextToken } }
  10. [実行] (オレンジ色の再生ボタン) を選択し、[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 } } }

セット型の使用

ここまでの Post 型は、フラットなキーと値のオブジェクトでした。 リゾルバーを使用して、セット型、リスト型、マップ型などの複雑なオブジェクトをモデル化することもできます。Post 型を更新して、タグを含めましょう。1 つのポストには、DynamoDB に文字列として保存されているタグを 0 個以上付けることができます。タグを追加および削除するミューテーションと、特定のタグが付いているポストをスキャンする新しいクエリもセットアップします。

データを設定するには

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

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

    type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! tags: [String!] }
  3. [スキーマ] ペインの 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 }
  4. [スキーマ] ペインの Mutation タイプを変更して、新しい addTagremoveTag ミューテーションを次のように追加します。

    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! }
  5. [Save Schema] を選択します。

  6. 右側のリゾルバーペインで、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 }; }
  7. リゾルバーに加えた変更を保存します。

  8. 次に、以下のスニペットを使って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
  9. リゾルバーに加えた変更を保存します。

  10. 以下のスニペットを使用して、これを 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
  11. リゾルバーに加えた変更を保存します。

タグを操作するAPIには、 を呼び出します。

リゾルバーをセットアップしたので、受信する addTag、、removeTagおよび allPostsByTagリクエストを DynamoDB UpdateItemおよび Scanオペレーションに変換する AWS AppSync 方法について説明します。それを試すには、前のステップで作成したポストのいずれかを選択します。例えば、Nadia が作成したポストを使用しましょう。

タグを使用するには

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

  2. 以下のクエリをクエリペインに貼り付けます。

    query allPostsByAuthor { allPostsByAuthor( author: "Nadia" ) { posts { id title } nextToken } }
  3. [実行] (オレンジ色の再生ボタン) を選択し、[allPostsByAuthor] を選択します。

  4. Nadia のすべてのポストが、クエリペインの右側にある結果ペインに表示されます。これは次のように表示されます。

    { "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you known...?" } ], "nextToken": null } } }
  5. タイトルが「The cutest dog in the world」の投稿を使用しましょう。id は後で使用するため書き留めておきます。では、dog タグを追加してみましょう。

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

    mutation addTag { addTag(id:10 tag: "dog") { id title tags } }
  7. [実行] (オレンジ色の再生ボタン) を選択し、[addTag] を選択します。ポストが新しいタグで更新されています。

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }
  8. タグを追加することができます。puppy に変更するように、tag 引数を更新します。

    mutation addTag { addTag(id:10 tag: "puppy") { id title tags } }
  9. [実行] (オレンジ色の再生ボタン) を選択し、[addTag] を選択します。投稿が新しいタグで更新されています。

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } } }
  10. タグを削除することもできます。以下のミューテーションを [クエリ] ペインに貼り付けます。また、id 引数を、前にメモしておいた値に更新する必要があります。

    mutation removeTag { removeTag(id:10 tag: "puppy") { id title tags } }
  11. [実行] (オレンジ色の再生ボタン) を選択し、[removeTag] を選択します。ポストが更新され、puppy タグが削除されています。

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }
  12. タグが付いているすべての投稿を検索することもできます。以下のクエリをクエリペインに貼り付けます。

    query allPostsByTag { allPostsByTag(tag: "dog") { posts { id title tags } nextToken } }
  13. [実行] (オレンジ色の再生ボタン) を選択し、[allPostsByTag] を選択します。次のように dog タグが付いているすべての投稿が返されます。

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

結論

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

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

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

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