【Go】GraphQL で DB から値を取ってきて返す
Go の GraphQL ライブラリである gqlgen を用いて DB から値を取ってきて返す Query を作る。
開発環境
- go 1.17
- github.com/99designs/gqlgen v0.17.1
- github.com/graph-gophers/dataloader v5.0.0+incompatible
本文
注意:gqlgen は開発が活発であり、バージョンが違うとチュートリアルの内容すらも変わるため、この記事を鵜呑みにしないでください。
DB にあらかじめ架空のブログサービスを想定した初期データを投入しておき、幾つかの Query のみ作成した。
今回の完成品は下記なので、詳しくは下記参照。この記事ではかいつまんで記載する。
https://gitlab.com/k1350/daybreak_sample/-/tree/graphql_query_sample
ひな形作成時の詰まりポイント
まず gqlgen の Getting Started に従ってひな形を作ると思うのだが
https://gqlgen.com/getting-started/
ここ一週間の間にいつのまにか gqlgen のバージョンが v0.17.1 に上がっていて、2022/03/05 現在まだ公式の Getting Started に v0.17.1 の内容が書いていない。
v0.17.1 で注意すべきなのは gqlgen.yml の autobind が最初からコメントアウトされていることである。
それによって Getting Started(v0.16.0 版) の “Don’t eagerly fetch the user” という部分で graph/model/todo.go
を作成後、そのまま
go run github.com/99designs/gqlgen generate
というコマンドを打つと Todo
の定義が重複しているというエラーとなる。
回避方法はリポジトリの README に書いてある通り gqlgen.yml
にカスタムモデルを明示的に指定する。
# gqlgen.yml
models:
Todo:
model: github.com/[username]/gqlgen-todos/graph/model.Todo
このように指定してから
go run github.com/99designs/gqlgen generate
を打てば models_gen.go
から自動生成のモデルが消える。
MySQL のコネクションを resolver に渡す
自動生成された graph/resolver.go
にて、Resolver に DB を持たせておく。
type Resolver struct {
DB *sql.DB
}
DB への接続は server.go
内で行い、server.go
の下記の部分で Resolver に DB を渡す。
srv := handler.NewDefaultServer(
generated.NewExecutableSchema(
generated.Config{Resolvers: &graph.Resolver{DB: db}},
),
)
こうすることで graph/schema.resolvers.go
内ではレシーバから DB を取ることができる。
func (r *queryResolver) Blogs(ctx context.Context) ([]*model.Blog, error) {
// ログインユーザーのユーザーIDが取れるものとする
userId := -1
s := `
SELECT
id,
blog_key,
user_id,
name,
description,
publish_option,
created_at,
updated_at
FROM blog
WHERE user_id = ?
ORDER BY id DESC
`
rows, err := r.DB.Query(s, userId)
// 以下略
Dataloader
下記のように dataloader を使ったデータ取得処理を実装する。
※dataloader の使用方法を把握したくて実装したが、今回の実装だと dataloader を使う必要はなかった
どのタイミングで、どういう経路で DB を渡せばいいのかよくわからなかったのだが、server.go
で Middleware を呼ぶときに渡すことにした。
server.go
http.Handle("/query", graph.DataloaderMIddleware(db, srv))
ID について
github.com/99designs/gqlgen では ID を int 型にできるのだが、github.com/graph-gophers/dataloader のほうが int 型にできるのか調べてもわからなかったので文字列型のままにしている。
こういうのはデフォルトのままにしておくほうが良さそう。
次回以降
引き続き Query でページネーションを実装する。