翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
AWS AppSyncの Data API での Aurora PostgreSQL の使用
を使用して GraphQL API を Aurora PostgreSQL データベースに接続する方法について説明します AWS AppSync。この統合により、GraphQL オペレーションを介して SQL クエリとミューテーションを実行することで、スケーラブルなデータ駆動型アプリケーションを構築できます。 は、Data API で有効になっている Amazon Aurora クラスターに対して SQL ステートメントを実行するためのデータソース AWS AppSync を提供します。 AWS AppSync リゾルバーを使用して、GraphQL クエリ、ミューテーション、サブスクリプションを使用して、データ API に対して SQL ステートメントを実行できます。
このチュートリアルを開始する前に、 AWS サービスと GraphQL の概念に関する基本的な知識が必要です。
注記
このチュートリアルでは、US-EAST-1
リージョンを使用しています。
Aurora PostgreSQL データベースをセットアップする
Amazon RDS データソースを に追加する前に AWS AppSync、次の操作を行います。
Aurora Serverless v2 クラスターで Data API を有効にします。
を使用してシークレットを設定する AWS Secrets Manager
次の AWS CLI コマンドを使用してクラスターを作成します。
aws rds create-db-cluster \ --db-cluster-identifier appsync-tutorial \ --engine aurora-postgresql \ --engine-version 16.6 \ --serverless-v2-scaling-configuration MinCapacity=0,MaxCapacity=1 \ --master-username USERNAME \ --master-user-password COMPLEX_PASSWORD \ --enable-http-endpoint
これにより、クラスターの ARN が返されます。クラスターを作成したら、次の AWS CLI コマンドを使用して Serverless v2 インスタンスを追加する必要があります。
aws rds create-db-instance \ --db-cluster-identifier appsync-tutorial \ --db-instance-identifier appsync-tutorial-instance-1 \ --db-instance-class db.serverless \ --engine aurora-postgresql
注記
これらのエンドポイントがアクティブ化されるまでに時間がかかります。ステータスは、クラスターの接続とセキュリティタブの RDS コンソールで確認できます。
次の AWS CLI コマンドを使用して、クラスターのステータスを確認します。
aws rds describe-db-clusters \ --db-cluster-identifier appsync-tutorial \ --query "DBClusters[0].Status"
AWS Secrets Manager コンソールまたは を使用して、前のステップCOMPLEX_PASSWORD
の USERNAME
と を使用して、次のような入力ファイル AWS CLI を使用してシークレットを作成します。
{ "username": "USERNAME", "password": "COMPLEX_PASSWORD" }
これをパラメータとして に渡します AWS CLI。
aws secretsmanager create-secret \ --name appsync-tutorial-rds-secret \ --secret-string file://creds.json
これにより、シークレットの ARN が返されます。 AWS AppSync コンソールでデータソースを作成するときは、Aurora Serverless v2 クラスターの ARN と のシークレットを書き留めます。
データベースとテーブルの作成
まず、 という名前のデータベースを作成しますTESTDB
。PostgreSQL では、データベースはテーブルやその他の SQL オブジェクトを保持するコンテナです。API に追加 AWS AppSync する前に、Aurora Serverless v2 クラスターが正しく設定されていることを確認します。まず、次のように --sql
パラメータを使用して TESTDB データベースを作成します。
aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:111122223333 ISN:cluster:appsync-tutorial" \ --secret-arn "arn:aws:secretsmanager:us-east-1:111122223333 ISN:secret:appsync-tutorial-rds-secret" \ --sql "create DATABASE \"testdb\"" \ --database "postgres"
これがエラーなしで実行されたら、create table
コマンドを使用して 2 つのテーブルを追加します。
aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:111122223333 ISN:cluster:appsync-tutorial" \ --secret-arn "arn:aws:secretsmanager:us-east-1:111122223333 ISN:secret:appsync-tutorial-rds-secret" \ --database "testdb" \ --sql 'create table public.todos (id serial constraint todos_pk primary key, description text not null, due date not null, "createdAt" timestamp default now());' aws rds-data execute-statement \ --resource-arn "arn:aws:rds:us-east-1:111122223333 ISN:cluster:appsync-tutorial" \ --secret-arn "arn:aws:secretsmanager:us-east-1:111122223333 ISN:secret:appsync-tutorial-rds-secret" \ --database "testdb" \ --sql 'create table public.tasks (id serial constraint tasks_pk primary key, description varchar, "todoId" integer not null constraint tasks_todos_id_fk references public.todos);'
成功したら、クラスターを API のデータソースとして追加します。
GraphQL スキーマを作成する
Aurora Serverless v2 Data API が設定されたテーブルで実行されたので、GraphQL スキーマを作成します。API 作成ウィザードを使用して既存のデータベースからテーブル設定をインポートすることで、API をすばやく作成できます。
開始方法
-
AWS AppSync コンソールで API の作成を選択し、Amazon Aurora クラスターから開始します。
-
[API 名] などの API の詳細を指定し、API を生成するデータベースを選択します。
-
データベースを選択します。必要に応じてリージョンを更新し、Aurora クラスターと TESTDB データベースを選択します。
-
シークレットを選択し、[インポート] を選択します。
-
テーブルが検出されたら、型名を更新します。
Todos
をTodo
に変更し、Tasks
をTask
に変更します。 -
[スキーマをプレビュー] を選択して、生成されたスキーマをプレビューします。スキーマは以下のようになります。
type Todo { id: Int! description: String! due: AWSDate! createdAt: String } type Task { id: Int! todoId: Int! description: String }
-
ロールの場合、 で AWS AppSync 新しいロールを作成するか、次のようなポリシーで作成できます。
このポリシーには、ロールにアクセス許可を付与するステートメントが 2 つあることに注意してください。最初のリソースは Aurora クラスターで、2 番目のリソースは AWS Secrets Manager ARN です。
[次へ] を選択し、設定の詳細を確認して [API の作成] を選択します。これで完全に動作する API が作成されました。API の全詳細は、[スキーマ] ページで確認できます。
RDS のリゾルバー
API 作成フローでは、型とやり取りするリゾルバーが自動的に作成されました。スキーマページを見ると、リゾルバーの一部が表示されます。
-
Mutation.createTodo
フィールドでtodo
を作成する。 -
Mutation.updateTodo
フィールドでtodo
を更新する。 -
Mutation.deleteTodo
フィールドでtodo
を削除する。 -
Query.getTodo
フィールドで 単一のtodo
を取得する。 -
Query.listTodos
フィールドでtodos
をすべて一覧表示する。
Task
型にアタッチされた類似のフィールドとリゾルバーがあります。いくつかのリゾルバーを詳しく見ていきましょう。
Mutation.createTodo
AWS AppSync コンソールのスキーマエディタの右側で、 testdb
の横にある を選択しますcreateTodo(...): Todo
。リゾルバーコードは、rds
モジュールの insert
関数を使用して、todos
テーブルにデータを追加する挿入ステートメントを動的に作成します。ここでは Postgres を使用しているため、挿入されたデータをreturning
ステートメントを活用して返すことができます。
次のリゾルバーを更新して、 due
フィールドDATE
のタイプを適切に指定します。
import { util } from '@aws-appsync/utils'; import { insert, createPgStatement, toJsonObject, typeHint } from '@aws-appsync/utils/rds'; export function request(ctx) { const { input } = ctx.args; // if a due date is provided, cast is as `DATE` if (input.due) { input.due = typeHint.DATE(input.due) } const insertStatement = insert({ table: 'todos', values: input, returning: '*', }); return createPgStatement(insertStatement) } export function response(ctx) { const { error, result } = ctx; if (error) { return util.appendError( error.message, error.type, result ) } return toJsonObject(result)[0][0] }
リゾルバーを保存します。型ヒントは、入力オブジェクト内の due
をDATE
型として適切にマークします。これにより、Postgres エンジンが値を適切に解釈できるようになります。次に、スキーマを更新して CreateTodo
入力から id
を削除します。Postgres データベースは生成された ID を返すことができるため、次のように 1 回のリクエストで作成して返すことができます。
input CreateTodoInput { due: AWSDate! createdAt: String description: String! }
変更を加え、スキーマを更新します。クエリエディタに移動して、次のようにデータベースに項目を追加します。
mutation CreateTodo { createTodo(input: {description: "Hello World!", due: "2023-12-31"}) { id due description createdAt } }
次の結果が得られます。
{ "data": { "createTodo": { "id": 1, "due": "2023-12-31", "description": "Hello World!", "createdAt": "2023-11-14 20:47:11.875428" } } }
Query.listTodos
コンソールのスキーマエディタの右側で、listTodos(id: ID!): Todo
の横にある testdb
を選択します。リクエストハンドラーは select ユーティリティ関数を使用して、実行時にリクエストを動的に構築します。
export function request(ctx) { const { filter = {}, limit = 100, nextToken } = ctx.args; const offset = nextToken ? +util.base64Decode(nextToken) : 0; const statement = select({ table: 'todos', columns: '*', limit, offset, where: filter, }); return createPgStatement(statement) }
due
の日付に基づいて todos
をフィルタリングしたいとします。due
の値を DATE
にキャストするようにリゾルバーを更新しましょう。インポートのリストとリクエストハンドラーを次のように更新します。
import { util } from '@aws-appsync/utils'; import * as rds from '@aws-appsync/utils/rds'; export function request(ctx) { const { filter: where = {}, limit = 100, nextToken } = ctx.args; const offset = nextToken ? +util.base64Decode(nextToken) : 0; // if `due` is used in a filter, CAST the values to DATE. if (where.due) { Object.entries(where.due).forEach(([k, v]) => { if (k === 'between') { where.due[k] = v.map((d) => rds.typeHint.DATE(d)); } else { where.due[k] = rds.typeHint.DATE(v); } }); } const statement = rds.select({ table: 'todos', columns: '*', limit, offset, where, }); return rds.createPgStatement(statement); } export function response(ctx) { const { args: { limit = 100, nextToken }, error, result, } = ctx; if (error) { return util.appendError(error.message, error.type, result); } const offset = nextToken ? +util.base64Decode(nextToken) : 0; const items = rds.toJsonObject(result)[0]; const endOfResults = items?.length < limit; const token = endOfResults ? null : util.base64Encode(`${offset + limit}`); return { items, nextToken: token }; }
クエリエディタで、次の操作を行います。
query LIST { listTodos(limit: 10, filter: {due: {between: ["2021-01-01", "2025-01-02"]}}) { items { id due description } } }
Mutation.updateTodo
Todo
を update
することも可能です。[クエリ] エディタから、id
1
の最初の Todo
項目を更新しましょう。
mutation UPDATE { updateTodo(input: {id: 1, description: "edits"}) { description due id } }
更新する項目の id
を指定する必要があることに注意してください。条件を指定して、特定の条件を満たす項目のみを更新することもできます。たとえば、説明がedits
次のように で始まる場合にのみ項目を編集できます。
mutation UPDATE { updateTodo(input: {id: 1, description: "edits: make a change"}, condition: {description: {beginsWith: "edits"}}) { description due id } }
create
オペレーションと list
オペレーションを処理したのと同じように、リゾルバーを更新して due
フィールドを DATE
にキャストできます。これらの変更をupdateTodo
次のように に保存します。
import { util } from '@aws-appsync/utils'; import * as rds from '@aws-appsync/utils/rds'; export function request(ctx) { const { input: { id, ...values }, condition = {}, } = ctx.args; const where = { ...condition, id: { eq: id } }; // if `due` is used in a condition, CAST the values to DATE. if (condition.due) { Object.entries(condition.due).forEach(([k, v]) => { if (k === 'between') { condition.due[k] = v.map((d) => rds.typeHint.DATE(d)); } else { condition.due[k] = rds.typeHint.DATE(v); } }); } // if a due date is provided, cast is as `DATE` if (values.due) { values.due = rds.typeHint.DATE(values.due); } const updateStatement = rds.update({ table: 'todos', values, where, returning: '*', }); return rds.createPgStatement(updateStatement); } export function response(ctx) { const { error, result } = ctx; if (error) { return util.appendError(error.message, error.type, result); } return rds.toJsonObject(result)[0][0]; }
次に、以下の条件で更新を試してください。
mutation UPDATE { updateTodo( input: { id: 1, description: "edits: make a change", due: "2023-12-12"}, condition: { description: {beginsWith: "edits"}, due: {ge: "2023-11-08"}}) { description due id } }
Mutation.deleteTodo
deleteTodo
ミューテーションで Todo
を delete
できます。これはミューupdateTodo
テーションと同様に機能し、次のように削除する項目の id
を指定する必要があります。
mutation DELETE { deleteTodo(input: {id: 1}) { description due id } }
カスタムクエリの記述
rds
モジュールユーティリティを使用して SQL ステートメントを作成しました。独自でカスタムした静的ステートメントを記述して、データベースとやり取りすることもできます。まず、スキーマを更新して CreateTask
入力から id
フィールドを削除します。
input CreateTaskInput { todoId: Int! description: String }
次に、いくつかのタスクを作成します。タスクには、Todo
次のように との外部キー関係があります。
mutation TASKS { a: createTask(input: {todoId: 2, description: "my first sub task"}) { id } b:createTask(input: {todoId: 2, description: "another sub task"}) { id } c: createTask(input: {todoId: 2, description: "a final sub task"}) { id } }
getTodoAndTasks
次のように、 Query
というタイプに新しいフィールドを作成します。
getTodoAndTasks(id: Int!): Todo
次のように Todo
タイプにtasks
フィールドを追加します。
type Todo { due: AWSDate! id: Int! createdAt: String description: String! tasks:TaskConnection }
スキーマを保存します。コンソールのスキーマエディタの右側で、getTodosAndTasks(id:
Int!): Todo
に対して [リゾルバーをアタッチ] を選択します。Amazon RDS データソースを選択します。次のコードでリゾルバーを更新します。
import { sql, createPgStatement,toJsonObject } from '@aws-appsync/utils/rds'; export function request(ctx) { return createPgStatement( sql`SELECT * from todos where id = ${ctx.args.id}`, sql`SELECT * from tasks where "todoId" = ${ctx.args.id}`); } export function response(ctx) { const result = toJsonObject(ctx.result); const todo = result[0][0]; if (!todo) { return null; } todo.tasks = { items: result[1] }; return todo; }
このコードでは、sql
タグテンプレートを使用して、実行時に動的な値を安全に渡すことができる SQL ステートメントを記述します。createPgStatement
は、一度に最大 2 つの SQL リクエストを受け入れることができます。これを利用して、todo
に対して 1 つのクエリを送信し、tasks
に対して別のクエリを送信します。これは、JOIN
ステートメントやその他の方法を使用して行うこともできます。つまり、独自の SQL ステートメントを記述してビジネスロジックを実装できるということです。クエリエディタでクエリを使用するには、次の手順を実行します。
query TodoAndTasks { getTodosAndTasks(id: 2) { id due description tasks { items { id description } } } }
クラスターの削除
重要
クラスターは完全に削除されます。このアクションを実行する前に、プロジェクトを徹底的に確認してください。
クラスターを削除するには
$ aws rds delete-db-cluster \ --db-cluster-identifier appsync-tutorial \ --skip-final-snapshot