Movatterモバイル変換


[0]ホーム

URL:


虎の穴ラボ技術ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

Amplifyにおける複数モデルのGraphQL APIについて

虎の穴ラボのかのたんです。

AWSが公式で提供しているAmplifyという開発ツールは非常に簡単、かつ高速にAPI環境が構築できるということで注目度が上がっており、AWSの公式セミナーや勉強会等でも取り上げられる機会が増えています。

弊社でも有志でAmplifyの使い方についての調査を行っており、特に以前弊社のNSSさんがブログに投稿したAmplifyに関する記事は非常に多くの方に読んでいただきました。

toranoana-lab.hatenablog.com

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”)

f:id:toranoana-lab:20220107142115p:plain

の方を選んでみましょう。するとこういったコードが生成されます。

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つのブログを作成します。

# requestmutation MyMutation {  createBlog(input: {name: "ブログ01"})}# response{  "data": {    "createBlog": {      "id": "0ee8fb8d-ddca-404c-878b-1465fd782381"    }  }}
# requestmutation 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を入れます。

# Requestmutation MyMutation {  createPost(    input: {title: "投稿01-01", blogPostsId: "0ee8fb8d-ddca-404c-878b-1465fd782381"}  ) {    id  }}# Response{  "data": {    "createPost": {      "id": "27179845-0f8f-40bb-b202-5a85ea054696"    }  }}
# Requestmutation MyMutation {  createPost(    input: {title: "投稿01-02", blogPostsId: "0ee8fb8d-ddca-404c-878b-1465fd782381"}  ) {    id  }}# Response{  "data": {    "createPost": {      "id": "cf02932b-737f-4460-a085-47eb8dcc3b92"    }  }}
# Requestmutation 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を入れます。

# Requestmutation MyMutation {  createComment(input: {content: "コメント01-01-01", postCommentsId: "27179845-0f8f-40bb-b202-5a85ea054696"}) {    id  }}# Response{  "data": {    "createComment": {      "id": "97da2b9d-7dd1-42d8-a7a0-36a21e6a0eba"    }  }}
# Requestmutation 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 を取得しているところがネストされた関連モデルを一気に取得するためのポイントです。

# Requestquery 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上ではこのように見えます。

f:id:toranoana-lab:20220112162115p:plain

f:id:toranoana-lab:20220112162125p:plain

無事にblogs→posts→commentsの順で取得できました。

listCommentsによるコメント一覧の取得

続いてlistCommentsを使って、コメント一覧を取得します。

今度は先ほどとは逆の順で、comments の中でpostを、posts の中でblog を取得することで、親モデルへと辿っているところがポイントです。

# Requestquery 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上ではこのように見えます。

f:id:toranoana-lab:20220112162221p:plain

f:id:toranoana-lab:20220112162230p:plain

無事に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

エンジニア・ディレクター積極採用中!

採用サイトはこちら
検索
注目記事

引用をストックしました

引用するにはまずログインしてください

引用をストックできませんでした。再度お試しください

限定公開記事のため引用できません。

読者です読者をやめる読者になる読者になる

[8]ページ先頭

©2009-2025 Movatter.jp