Help us understand the problem. What is going on with this article?

AWS AppSyncで一対多の関連を1リクエストで取得する

概要

AWS AppSyncはAWS上にGraphQLサーバーを構築することができるマネージドサービスです。
GraphQLの特徴の一つとして、取得するフィールドをクライアント側から指定することができる点があります。

GraphQLとネストされたフィールド

GraphQLスキーマでは、ある型のフィールドに他の型を指定することもできます。

GraphQLスキーマ
type User {
  name: String!
  posts: [Post]
}

type Post {
  id: ID!
  content: String!
  user: User!
}

このスキーマに適切にリゾルバーをアタッチすることで、

  • Postとそれを作成したユーザーを取得
  • ユーザーとそのユーザーが作成したPostの配列を取得

といったデータを1リクエストで要求できるようになります。

疑問点

上の例のようにUserPostというモデルがあり、それをUserTablePostTableというテーブルに別々に格納していたとします。
PostTableにはuserIdという属性があり、これがテーブル間を結合する外部キーになります。

さて、ネストされたフィールドを含めてデータを取得するGraphQLクエリは以下のようになります。

GraphQLクエリ
query getPost {
  getPost(id: "99999") {
    id
    content
    user {
      name
    }
  }
}

Postはクエリの引数として与えられたid = 99999で特定することができます。
しかし、Postを作成したUserはどのように特定すれば良いのでしょうか?
GraphQLスキーマには、あるフィールドを外部キーとしてマークする仕様はありません。

フィールドにリゾルバーをアタッチする

Post.userUser型だから、userIdという名前で自動的にJOINしてくれる、ということはありません。
目的の動作を実現するには、Post.userに対してリゾルバーをアタッチします。

AppSyncのフィールドにリゾルバーをアタッチ

リゾルバーのデータソースは、今回であればUserTableからデータを取得したいのでUserTableに対応するデータソースを指定します。
マッピングテンプレートはシンプルに一件アイテムを取得する命令を書けばOKです。

今回はデータソースにAmazon DynamoDBを利用しているので、以下のようになります。

リクエストマッピングテンプレート
{
  "version": "2017-02-28",
  "operation": "GetItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($ctx.source.userId),
  }
}
レスポンスマッピングテンプレート
$util.toJson($ctx.result)

ポイントはリクエストマッピングテンプレート中の$ctx.source.userIdの部分です。
この$ctx.sourceに、getPostクエリの実行結果が格納されているので、それを使ってUserTableにデータを取りに行きます。

まとめ

モバイルアプリ / SPAを開発していると、一画面で必要となる情報が複数モデルにまたがってリクエスト数が増えたり、それらをまとめた使い回しがききにくいエンドポイントを作ったりという課題が発生するかと思います。

GraphQLを使うことで、複数エンティティにまたがるデータの取得も非常にシンプルに実現することができます。

今までRESTを使っていて、GraphQLを使い始めるに当たって戸惑ったことがいくつかあるので、それらを少しずつまとめていけたらと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした