こんにちは。アプリケーションサービス部 河野です。
AWS Amplify(以下 Amplify) は CRUD 処理を含んだリゾルバーを自動的に生成することができますが、
それ以外の処理を実現したい場合は、カスタムリゾルバーを追加する必要があります。
例えば、一回のリクエストで複数のテーブルを更新したい、複数のデータを処理したいなどといった場合です。
今回は、デフォルトで作成したスキーマに、複数件登録できるカスタムリゾルバーを追加します。
前提
amplify init 後に以下スキーマが追加されている状態です。
(amplify add api
でデフォルトスキーマを作成した状態)
type Todo @model { id: ID! name: String! description: String }
やりたいこと
一回のリクエストで、 Todo テーブルに複数件登録できることを目指します。
@model
で宣言されたリゾルバーを使用すれば、createTodo(input: {name: "hoge"})
といった形でデータを登録できます。
やりたいことは、createBatchTodo(input: [{name: "hoge"}, {name: "fuga"}])
といった形で、引数にリストを渡して、複数件登録することです。
実装
Mutation の追加
まずは、schema.graphql
に複数件登録する Mutation
を追加します。
input TodoInput { id: ID name: String! description: String } type Mutation { batchAddTodo(todos: [TodoInput]): [Todo] batchDeleteTodo(ids: [ID]): [Todo] }
batchAddTodo
は、TodoInput
のリストを引数に持ちます。ID はリゾルバー側で自動生成させるため、必須にしていません。
batchDeleteTodo
は ID リストを引数にもち、一致した ID を一括削除します。
カスタムリゾルバーの作成
カスタムリゾルバーは、amplify/backend/api/{your_api_name}/resolvers
に追加します。
以下リゾルバーを作成します。
- Mutation.batchAddTodo.req.vtl
- Mutation.batchAddTodo.res.vtl
- Mutation.batchDeleteTodo.res.vtl
- Mutation.batchDeleteTodo.res.vtl
Mutation.batchAddTodo.req.vtl
batchAddTodo
実行時のリクエストリゾルバーを定義します。
#set($data = []) #set( $createdAt = $util.time.nowISO8601() ) #foreach($item in ${ctx.args.todos}) $util.qr($item.put("id", $util.defaultIfNullOrBlank($item.id, $util.autoId()))) $util.qr($item.put("createdAt", $util.defaultIfNull($item.createdAt, $createdAt))) $util.qr($item.put("updatedAt", $util.defaultIfNull($item.updatedAt, $createdAt))) $util.qr($data.add($util.dynamodb.toMapValues($item))) #end { "version" : "2018-05-29", "operation" : "BatchPutItem", "tables" : { "Todo-xxxxxxxxxxx-dev": $util.toJson($data) } }
引数で渡ってきたリストを、DynamoDB の BatchPutItem
のパラメータを生成しているイメージです。
生成時に、id, createdAt, updatedAt を付与しています。
tables で指定している テーブル名は AppSync のデータソースから参照できます。
BatchPutItem
を使用した複数件登録については、以下チュートリアルに記載されておりますのでご参考ください。
Mutation.batchAddTodo.res.vtl
batchAddTodo
実行時のレスポンスリゾルバーを定義します。
#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result.data.Todo-xxxxxxxxxxx-dev) #end
レスポンスは特に手を加えずに、DynamoDB から取得したデータををそのまま返します。
Mutation.batchDeleteTodo.req.vtl
#set($ids = []) #foreach($id in ${ctx.args.ids}) #set($map = {}) $util.qr($map.put("id", $util.dynamodb.toString($id))) $util.qr($ids.add($map)) #end { "version" : "2018-05-29", "operation" : "BatchDeleteItem", "tables" : { "Todo-xxxxxxxxxxx-dev": $util.toJson($ids) } }
batchAddTodo
と考え方は同じで、リストで受け取った id をもとに、BatchDeleteItem
のパラメータを作成しています。
Mutation.batchDeleteTodo.res.vtl
#if( $ctx.error ) $util.error($ctx.error.message, $ctx.error.type) #else $util.toJson($ctx.result.data.Todo-xxxxxxxxxxx-dev) #end
batchAddTodo
と同様、特に手を加えずに、DynamoDB から取得したデータををそのまま返します。
マッピングリソース作成
Amplify でカスタムリゾルバーをデプロイするためには、amplify/backend/api/{your_api_name}/stacks/CustomResource.json
に追記する必要があります。
以下は、新しくスキーマに追加した Mutation に 先ほど定義したカスタムリゾルバーをマッピングする CloudFormation を定義しています。
"Resources": { "EmptyResource": { "Type": "Custom::EmptyResource", "Condition": "AlwaysFalse" }, "batchAddTodoResolver": { "Type": "AWS::AppSync::Resolver", "Properties": { "ApiId": { "Ref": "AppSyncApiId" }, "DataSourceName": "TodoTable", "TypeName": "Mutation", "FieldName": "batchAddTodo", "RequestMappingTemplateS3Location": { "Fn::Sub": [ "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Mutation.batchAddTodo.req.vtl", { "S3DeploymentBucket": { "Ref": "S3DeploymentBucket" }, "S3DeploymentRootKey": { "Ref": "S3DeploymentRootKey" } } ] }, "ResponseMappingTemplateS3Location": { "Fn::Sub": [ "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Mutation.batchAddTodo.res.vtl", { "S3DeploymentBucket": { "Ref": "S3DeploymentBucket" }, "S3DeploymentRootKey": { "Ref": "S3DeploymentRootKey" } } ] } } }, "batchDeleteTodoResolver": { "Type": "AWS::AppSync::Resolver", "Properties": { "ApiId": { "Ref": "AppSyncApiId" }, "DataSourceName": "TodoTable", "TypeName": "Mutation", "FieldName": "batchDeleteTodo", "RequestMappingTemplateS3Location": { "Fn::Sub": [ "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Mutation.batchDeleteTodo.req.vtl", { "S3DeploymentBucket": { "Ref": "S3DeploymentBucket" }, "S3DeploymentRootKey": { "Ref": "S3DeploymentRootKey" } } ] }, "ResponseMappingTemplateS3Location": { "Fn::Sub": [ "s3://${S3DeploymentBucket}/${S3DeploymentRootKey}/resolvers/Mutation.batchDeleteTodo.res.vtl", { "S3DeploymentBucket": { "Ref": "S3DeploymentBucket" }, "S3DeploymentRootKey": { "Ref": "S3DeploymentRootKey" } } ] } } } }
デプロイ
以下コマンドでAWS環境にデプロイします。
amplify push -y
動作確認
想定通りの挙動になっているか、appsync のクエリ画面から実行してみます。
複数追加
複数削除
終わりに
今回は、Mutation のカスタムリゾルバーを作成しましたが、更に複雑な処理をしたい場合は、
クエリーから、AWS Lambda を呼び出すといったことも可能です。
今後もいろいろ試していきたいと思います。