端的に言うと、AppSync + DynamoDBで自動生成されたリゾルバを使ってデータ削除しようとしたら、次のエラーが出た時の対応です。
"The variables input contains a field that is not defined for input object type 'DeleteHogeHoge' "結論的には、DynamoDBのソートキーが無視されたリゾルバになっていました。
はじめに
AWS Amplifyは、Webおよびモバイルアプリケーションの開発を迅速化するためのツールセットです。Amplifyを使用すると、認証、データストレージ、APIなどの機能を簡単に実装できます。特に、GraphQL APIの作成とデプロイに関しては、AWS AppSyncが強力な支援を提供します。
AWS AppSyncは、開発者が効率的にGraphQL APIを構築し、管理できるように設計されたフルマネージドサービスです。AppSyncは、データのリアルタイム同期やオフラインデータアクセスなど、複雑なデータ操作を簡単に処理できることで知られています。
しかし、これらのツールは自動化されたプロセスに頼っているため、特定のデータモデルやユースケースに対する細かいカスタマイズが必要な場合、問題が生じることがあります。私が直面した問題は、AWS Amplifyが提供する自動コード生成機能と、DynamoDBの複合プライマリキーを使用したテーブル設計の間の整合性に関するものでした。
AppSyncとDynamoDBの基本
AWS AppSyncとDynamoDBは、AWSエコシステムの中で重要な位置を占めています。これらのサービスを理解することは、モダンなクラウドベースのアプリケーション開発において不可欠です。
AWS AppSync
AWS AppSyncは、データ駆動型のアプリケーションにおいてリアルタイムのデータ同期と通信を容易にするマネージドGraphQLサービスです。AppSyncを使用すると、フロントエンド開発者はバックエンドの複雑さを意識せずに、必要なデータを簡単に取得、変更、購読することができます。
GraphQLスキーマを定義することで、AppSyncはそのスキーマに基づいてAPIを生成します。例えば、本のデータモデルに対する簡単なGraphQLスキーマは次のようになります:
type Book {
book_id: ID!
title: String
author: String
...
}
type Query {
getBook(book_id: ID!): Book
listBooks: [Book]
}
type Mutation {
addBook(book: BookInput): Book
deleteBook(book_id: ID!): Book
}DynamoDB
DynamoDBは、高速かつ柔軟なNoSQLデータベースサービスで、キー-バリューおよびドキュメントデータモデルをサポートしています。DynamoDBは、パーティションキーとソートキーを組み合わせた複合プライマリキーを使ってデータをユニークに識別します。
例えば、本の情報を格納するDynamoDBテーブルの設計は次のようになります:
{
"TableName": "Books",
"KeySchema": [
{ "AttributeName": "user_id", "KeyType": "HASH" }, // パーティションキー
{ "AttributeName": "book_id", "KeyType": "RANGE" } // ソートキー
],
...
}ここでの問題は、AppSyncが自動的に生成するリゾルバがこの複合キー構造を正しく扱っていないことでした。次のセクションでは、この問題がどのように発生し、どのようにしてそれに気づいたのかを詳しく説明します。
問題の発生
プロジェクトの進行中に、AWS AppSyncとDynamoDBを使用してデータの保存と取得を行っていましたが、特定の操作で予期せぬ問題に直面しました。
自動生成されたリゾルバの問題
AWS AppSyncは、GraphQLスキーマに基づいてAPIを生成し、さらにDynamoDBテーブルとの間でデータを操作するためのリゾルバを自動生成します。私のプロジェクトでは、user_id と book_id を複合キーとするDynamoDBテーブルを用意していました。通常、このようなテーブル設計では、両方のキーを使用してデータを操作することが期待されます。
しかし、AppSyncが生成した削除操作のリゾルバは、book_id を無視し、user_id のみを使用してデータを削除しようとしていました。このため、期待通りにデータを削除できず、エラーが発生していました。
コードによる問題の特定
この問題に気づいたのは、削除操作を試行した際にエラーが発生し、データが削除されなかったことからでした。エラーメッセージを解析した結果、DynamoDBからのレスポンスが「提供されたキーエレメントがスキーマと一致しない」という内容であることを突き止めました。
AWS AppSyncのコンソールにアクセスし、リゾルバのコードを確認したところ、自動生成されたリゾルバが以下のようになっていることがわかりました:
/
* Deletes an item with user_Id `ctx.args.input.user_Id` from the DynamoDB table.
* @param {import('@aws-appsync/utils').Context<{input: {user_id: unknown;}}>} ctx the context
* @returns {import('@aws-appsync/utils').DynamoDBDeleteItemRequest} the request
*/
export function request(ctx) {
const { user_id } = ctx.args.input;
return {
operation: 'DeleteItem',
key: util.dynamodb.toMapValues({ user_id }),
}
}
このリゾルバは、book_id を考慮せずに user_id のみを使用しているため、複合キーを持つテーブルで適切な削除操作を行うことができませんでした。
次のセクションでは、この問題をどのように分析し、解決策をどのように導き出したかを詳しく説明します。
もちろんです。以下は、「問題の解析と解決策」セクションの詳細な文章です。
問題の解析と解決策
問題の根本的な原因
エラーメッセージの分析から、問題の根本原因がAppSyncの自動生成リゾルバにあることが明らかになりました。AppSyncは、スキーマ定義に基づいて削除操作のリゾルバを生成する際、DynamoDBテーブルの複合キー(user_id と book_id)を正しく扱っていませんでした。リゾルバは user_id のみを使用して削除を試み、book_id を完全に無視していました。
リゾルバの手動修正
この問題に対処するためには、リゾルバを手動で修正し、DynamoDBのテーブルキー構造に合わせる必要がありました。具体的には、リゾルバのリクエストマッピングテンプレートを次のように更新しました:
/
* Deletes an item with user_Id `ctx.args.input.user_Id` from the DynamoDB table.
* @param {import('@aws-appsync/utils').Context<{input: {user_id: unknown, book_id: unknown;}}>} ctx the context
* @returns {import('@aws-appsync/utils').DynamoDBDeleteItemRequest} the request
*/
export function request(ctx) {
const { user_id, book_id } = ctx.args.input;
return {
operation: 'DeleteItem',
key: util.dynamodb.toMapValues({ user_id, book_id }),
}
}
この修正により、リゾルバは user_id と book_id の両方を使用して削除操作を実行するようになり、DynamoDBのテーブルキー構造に適切に合わせられました。
まとめ
この記事を通じて、AWS AmplifyとAppSyncを利用する際に直面する可能性のある一つの典型的な問題とその解決策を共有しました。自動生成されたリゾルバがDynamoDBの複合キー構造を正しく扱わない場合の対処法と、その過程で得られた学びを詳しく説明しました。
- AWS AppSyncの自動生成リゾルバは、複雑なキースキーマを持つDynamoDBテーブルに対して常に適切ではない。
- データモデルや要件に応じてリゾルバを手動で検証し、調整することが重要。
- 基礎となるAWSサービスの動作と制約を理解することが、問題解決に不可欠。
AWS AmplifyとAppSyncは強力なツールですが、それらを最大限に活用するには、サービスの内部動作に対する深い理解が必要です。