AWS Amplify で GraphQL を使って API を作ってみる
タイトルの通り。
先日、AWS Amplify でホスティングを試してみた流れで、APIも作ってみようと思い立ったわけです。
Amplify ではコマンド一つでAPI(REST or GraphQL)を作ることができます。
GraphQL をちゃんと触った記憶がなかったので、せっかくなので試してみました。
GraphQL?
GraphQL って何?という話はいろんなところに書かれているので、ここでは割愛します。
雑に言ってしまえば、都合のいい形でデータ構造を決めてフロントエンドとバックエンドでデータのやりとりができるクエリ、という感じで認識してます。
Amplify で GraphQL を扱う場合、AppSync を利用することになります。
AppSync は GraphQL のバックエンドを構築するフルマネージドサービスなんですが、
・様々なデータソースへの接続
・オフライン対応
・リアルタイムアプリケーションの作成
・PubSub
などなど、かなり強力なサポートをしてくれます。
と書いていますが、難しいこと考えずに AWS でGraphQL使うんなら AppSync 使いましょうくらいの認識でいいかなと思ってます。
API の作成
ホスティングの時と同様に、amplify configure
で実行ユーザーのプロファイル設定、amplify init
でプロジェクトの初期設定を行います。
このあたりの記載については、先日のホスティングの記事と同様になります。
プロジェクトの初期設定が終わり、Amplify のコンソールでプロジェクトが確認できるようになったら、準備完了です。
以下のコマンドで API を追加します。
$ amplify add api
API の設定を選んでいきます。 今回は GraphQL で作るので、それに準じて選んでいます。
途中にある
What best describes your project
の選択肢で、データベースのリレーションについて選択することになります。
ここでは1対多を選んでいますが、この選択によって初期に作成されるスキーマの type 構成が変わってきます。
一般的に、独立したテーブルのみで作られるアプリケーションはあまりないと思うので、ここは基本的に1対多を選ぶ方がよいのかなと思ったりしました。
(もちろん、後からスキーマを変えてしまえばどちらでもいい話ではありますが。)
設定が終わると、スキーマにBlog
、Post
、Comment
が作成されます。
その後、
$ amplify push
を実行すると、AWS に GraphQL の API が作成されます。
スキーマの記述について
スキーマを書く上で、備忘録として残しておきたい書き方や注意などを以下にまとめます。
@model
スキーマにてテーブルの type を記載するとき、@model
ディレクティブを付与することで、プッシュ時にDynamoDBのテーブルを作成してくれます。
type Blog @model { id: ID! name: String! posts: [Post] @connection(keyName: "byBlog", fields: ["id"]) }
と同時に、基本的な CRUD についてのquery
やmutation
を自動生成し、input type
の定義まで行ってくれます。
正直、後から追加するテーブルの type を記述する場合、書かない手はないかなと思います。
リレーションの記述
今回作成した API では、Blog
、Post
、Comment
のテーブルへのアクセスがあります。
・Comment
は特定のPost
に対するコメントで、Post
とComment
は1:N
・Post
は特定のBlog
に対する投稿で、Blog
とPost
は1:N
という構造になっています。
この場合、各々の type を@connection
ディレクティブを使って紐づけていきます。
type Blog @model { id: ID! name: String! posts: [Post] @connection(keyName: "byBlog", fields: ["id"]) } type Post @model @key(name: "byBlog", fields: ["blogID"]) { id: ID! title: String! blogID: ID! blog: Blog @connection(fields: ["blogID"]) comments: [Comment] @connection(keyName: "byPost", fields: ["id"]) } type Comment @model @key(name: "byPost", fields: ["postID", "content"]) { id: ID! postID: ID! post: Post @connection(fields: ["postID"]) content: String! }
createdAtとupdatedAt
Amplify の仕様上、作成したテーブルにcreatedAt
とupdatedAt
という項目が自動で作成されます。
※スキーマに記述がなくとも、自動的に定義されます。
ここで少し厄介なのが、何も考えずにこれらの項目を作られると Not Null 制約がついてしまいます。
絶対的に必要な項目でもないのに Not Null が付くのは些か面倒なので、以下の方法で回避します。
■ Null を許容する
スキーマに明示的にcreatedAt
とupdatedAt
を記載することで、Null 許容の項目にすることができます。
type Blog @model { id: ID! name: String! posts: [Post] @connection(keyName: "byBlog", fields: ["id"]) createdAt: AWSDateTime updatedAt: AWSDateTime }
■ createdAt と updatedAt を作らない
@model
ディレクティブの記述を以下のようにしてやると、これらの項目が作られなくなります。
type Blog @model(timestamps: null)
蛇足ですが、デフォルトでは(記載がないだけで)以下のような記述として解釈されるらしいです。
type Blog @model(timestamps: {create: "createdAt", update: "updatedAt" })
このあたりで議論されてました
CRUDについてもまとめようと思いましたが、ちょっと長くなってしまった。。
とりあえず今日はここまで。