あらすじ
1.Apollo+Expressで始めるGraphQL超入門 ~ GraphQLをざっくり理解する
2.Apollo+Expressで始めるGraphQL超入門 ~ データ取得Lv1
GraphQLの設計について
GraphQLの作者の言葉をお借りすると「GraphQLはできるだけ薄く保つ」ということなので、ネストは深くしないのが望ましい。
なぜか
実際に私が陥った例を挙げると、簡易ECサイトをGraphQLで実装しようとしたとき
User
がItem
を買ったときの履歴PurchaseHistory
をGraphQLで取得できるAPIを作ろうと思った
type User {
id: ID!
name: String!
purchase_history: [Item]
}
type Item {
id: ID!
name: String!
catch_copy: String
}
User
の型に購入履歴をはじめからぶら下げる形で実装しようとした。
しかし、これでは User
の id
や name
だけ取得したい時に購入履歴まで取得するロジックが走ってしまう。
大体、購入履歴といえばItem
とのリレーションされたデータであり取得コストが大きいため
いくらキャッシュされるとはいえ、必要な情報だけが走る形で実装するのが望ましい。
どうするのか
GraphQLはQueryをまとめることができるので、薄く作ってあるQueryたちをまとめてほしい情報が取得できるQureyを新たに作る。
バックエンドで実装されているQuery
type Query {
user(id: String!): User
purchase_history(user_id: String!): [Purchase]
}
user
→ IDやユーザー名など取得できる
purchase_history
→ ユーザーの購入履歴が取得できる
各Qureyはそれぞれ user_id
を指定すればユーザーの情報を取得できる
しかし、このまま使ってしまうとリクエストを2つになってしまうため、GraphQLの特性を活かしきれていない。
Queryを1つにまとめる
user
と purchase_history
を1つのQueryで取得できるようにQueryを定義してあげよう
query getUserPurchaseHistory($user_id: String) {
user(id: $user_id) {
id
name
}
purchase_history(user_id: $user_id) {
id
name
catch_copy
}
}
getUserPurchaseHistory
に対して user_id
を渡すことで1つのリクエストで2つの情報をまとめて取得できる。
こうすることで、必要な情報を必要なときに取得でき、コストの掛かる処理も必要な時だけ行うことができる。
まとめ
またGraphQLの凄さを知ることができ、 GraphQLはできるだけ薄く保つ
の意味や意図が理解できました。
設計次第ではネストが深くなってしまい、部分的にしか使わないQueryが量産されてしまうこともあると思います。
そうなってしまうとGraphQLの良さがなくなってしまうので一旦立ち止まって できるだけ薄く
を意識することが大事ですね。
※ 筆者はまだまだ初心者です。間違った解釈や実装などがあればご指摘お願いします。