虎の穴ラボのかのたんです。
AWSが公式で提供しているAmplifyという開発ツールは非常に簡単、かつ高速にAPI環境が構築できるということで注目度が上がっており、AWSの公式セミナーや勉強会等でも取り上げられる機会が増えています。
弊社でも有志でAmplifyの使い方についての調査を行っており、特に以前弊社のNSSさんがブログに投稿したAmplifyに関する記事は非常に多くの方に読んでいただきました。
Amplifyの導入については、こちらのNSSさんの記事が非常に参考になります。
私の方でもAmplifyについて触ってみたので、今回の私の記事は上記のNSSさんの記事から派生するような形で、複数モデルのGraphQL APIの作り方について書きます。
GraphQL APIの作成
本記事の前提条件として、上記のNSSさんの記事等を参考にしてAmplifyのインストールやAmplifyプロジェクトの新規作成、AWS環境との連携などの初期設定を行ってください。
上記の記事に「AmplifyでAPIの実装」という項目がありますが、
$ amplify add api
を行ったあとの選択肢で
Single object with fields (e.g., “Todo” with ID, name, description)
というものを選んでます。今回はこのタイミングで
One-to-many relationship (e.g., “Blogs” with “Posts” and “Comments”)
の方を選んでみましょう。するとこういったコードが生成されます。
type Blog @model { id: ID! name: String! posts: [Post] @hasMany } type Post @model { id: ID! title: String! blog: Blog @belongsTo comments: [Comment] @hasMany } type Comment @model { id: ID! post: Post @belongsTo content: String! }
このコードを参考にすることで、複数モデルにまたがるGraphQLが作成可能です。
amplify mock api
で起動することにより、http://localhost:20002/
にてネストされたGraphQLのqueryが利用できることが確認できます。
いくつかテストデータを作って実行してみましょう。
Mutationによるデータ準備
GraphQLではMutationを使ってデータの作成、更新、削除を行います。
テストデータを作るために、CreateのMutationを使って各モデルにデータを入れていきます。
ブログ作成
ブログ01とブログ02という、2つのブログを作成します。
# request mutation MyMutation { createBlog(input: {name: "ブログ01"}) } # response { "data": { "createBlog": { "id": "0ee8fb8d-ddca-404c-878b-1465fd782381" } } }
# request mutation MyMutation { createBlog(input: {name: "ブログ02"}) } # response { "data": { "createBlog": { "id": "9b5eee80-5567-4f8d-89fd-3e4f68761c9a" } } }
ここで作成したブログのidをメモしておきます。
投稿作成
今度は投稿01-01と投稿01-02をブログ01に、投稿02-01をブログ02に紐づけてみます。
blogPostsIdが外部キーの役割を果たすので、投稿01-01と投稿01-02にはブログ01の、投稿02-01にはブログ02のidを入れます。
# Request mutation MyMutation { createPost( input: {title: "投稿01-01", blogPostsId: "0ee8fb8d-ddca-404c-878b-1465fd782381"} ) { id } } # Response { "data": { "createPost": { "id": "27179845-0f8f-40bb-b202-5a85ea054696" } } }
# Request mutation MyMutation { createPost( input: {title: "投稿01-02", blogPostsId: "0ee8fb8d-ddca-404c-878b-1465fd782381"} ) { id } } # Response { "data": { "createPost": { "id": "cf02932b-737f-4460-a085-47eb8dcc3b92" } } }
# Request mutation MyMutation { createPost( input: {title: "投稿02-01", blogPostsId: "9b5eee80-5567-4f8d-89fd-3e4f68761c9a"} ) { id } } # Response { "data": { "createPost": { "id": "3b392929-6b96-4286-bb96-8c71da7d6a49" } } }
今度は投稿のidをメモ。
コメントの作成
最後はコメントを作成します。投稿01-01にコメント01-01-01を、投稿02-01にコメント02-01-01を紐付けましょう。
先ほどと同様に、今度はpostCommentsIdにそれぞれの投稿のidを入れます。
# Request mutation MyMutation { createComment(input: {content: "コメント01-01-01", postCommentsId: "27179845-0f8f-40bb-b202-5a85ea054696"}) { id } } # Response { "data": { "createComment": { "id": "97da2b9d-7dd1-42d8-a7a0-36a21e6a0eba" } } }
# Request mutation MyMutation { createComment(input: {content: "コメント02-01-01", postCommentsId: "3b392929-6b96-4286-bb96-8c71da7d6a49"}) { id } } # Response { "data": { "createComment": { "id": "429717e3-438e-4536-a1e5-a2a1c9fc2409" } } }
これでデータの準備は完了です。
Queryによるデータ取得
GraphQLではQueryを使って更新を伴わないデータの参照を行います。
ここからはblogs→posts→commentsの順と、comments→post→blogの順の2パターンでデータを取得してみましょう。
listBlogsによるブログ一覧の取得
listBlogsを使って、ブログ一覧を取得します。
blogs
のitemsの中で posts
を、 posts
のitemsの中で comments
を取得しているところがネストされた関連モデルを一気に取得するためのポイントです。
# Request query MyQuery { listBlogs { items { id name posts { items { id title blogPostsId comments { items { id content postCommentsId } } } } } } } # Response { "data": { "listBlogs": { "items": [ { "id": "9b5eee80-5567-4f8d-89fd-3e4f68761c9a", "name": "ブログ02", "posts": { "items": [ { "id": "3b392929-6b96-4286-bb96-8c71da7d6a49", "title": "投稿02-01", "blogPostsId": "9b5eee80-5567-4f8d-89fd-3e4f68761c9a", "comments": { "items": [ { "id": "429717e3-438e-4536-a1e5-a2a1c9fc2409", "content": "コメント02-01-01", "postCommentsId": "3b392929-6b96-4286-bb96-8c71da7d6a49" } ] } } ] } }, { "id": "0ee8fb8d-ddca-404c-878b-1465fd782381", "name": "ブログ01", "posts": { "items": [ { "id": "cf02932b-737f-4460-a085-47eb8dcc3b92", "title": "投稿01-02", "blogPostsId": "0ee8fb8d-ddca-404c-878b-1465fd782381", "comments": { "items": [] } }, { "id": "27179845-0f8f-40bb-b202-5a85ea054696", "title": "投稿01-01", "blogPostsId": "0ee8fb8d-ddca-404c-878b-1465fd782381", "comments": { "items": [ { "id": "97da2b9d-7dd1-42d8-a7a0-36a21e6a0eba", "content": "コメント01-01-01", "postCommentsId": "27179845-0f8f-40bb-b202-5a85ea054696" } ] } } ] } } ] } } }
Graphiql上ではこのように見えます。
無事にblogs→posts→commentsの順で取得できました。
listCommentsによるコメント一覧の取得
続いてlistCommentsを使って、コメント一覧を取得します。
今度は先ほどとは逆の順で、comments
の中で post
を、 posts
の中で blog
を取得することで、親モデルへと辿っているところがポイントです。
# Request query MyQuery { listComments { items { id content postCommentsId post { id title blogPostsId blog { id name } } } } } # Response { "data": { "listComments": { "items": [ { "id": "97da2b9d-7dd1-42d8-a7a0-36a21e6a0eba", "content": "コメント01-01-01", "postCommentsId": "27179845-0f8f-40bb-b202-5a85ea054696", "post": { "id": "27179845-0f8f-40bb-b202-5a85ea054696", "title": "投稿01-01", "blogPostsId": "0ee8fb8d-ddca-404c-878b-1465fd782381", "blog": { "id": "0ee8fb8d-ddca-404c-878b-1465fd782381", "name": "ブログ01" } } }, { "id": "429717e3-438e-4536-a1e5-a2a1c9fc2409", "content": "コメント02-01-01", "postCommentsId": "3b392929-6b96-4286-bb96-8c71da7d6a49", "post": { "id": "3b392929-6b96-4286-bb96-8c71da7d6a49", "title": "投稿02-01", "blogPostsId": "9b5eee80-5567-4f8d-89fd-3e4f68761c9a", "blog": { "id": "9b5eee80-5567-4f8d-89fd-3e4f68761c9a", "name": "ブログ02" } } } ] } } }
Graphiql上ではこのように見えます。
無事にcomments→post→blogという関係も再現できました。
まとめ
今回はAmplifyを使った、複数モデルにまたがるGraphQL APIの作成と使用についてご紹介しました。
他にもAmplifyに関しては
- 認証・認可
- 絞り込みとソート
- enum型の使用
- 全文検索
など書けるネタが結構あるのですが、2021年12月18日にAmplifyのv2が出たことで記述方法が変わり、コードの追加検証が必要なため今回は断念しました。
公式ドキュメント等で書き換え方法についてサポートしてますので、v2の書き方に慣れていくのがよいかと思います。
https://docs.amplify.aws/cli/migration/transformer-migration/
Amplifyは若いプロジェクトなので新機能追加や仕様変更もあるかと思いますが、キャッチアップしながら使っていきましょう。
P.S.
採用情報
■募集職種
yumenosora.co.jp
カジュアル面談も随時開催中です
■お申し込みはこちら!
news.toranoana.jp
■ToraLab.fmスタートしました!
メンバーによるPodcastを配信中!
是非スキマ時間に聞いて頂けると嬉しいです。
anchor.fm
■Twitterもフォローしてくださいね!
ツイッターでも随時情報発信をしています
twitter.com