graphql-rubyにおけるN+1対策
使い方はREADMEに書いてあるけど、以下のようなLoaderを自分で定義する必要がある。(実際はexamplesフォルダの中身をコピーすれば良い) code: ruby
class RecordLoader < GraphQL::Batch::Loader
def initialize(model)
@model = model
end
def perform(ids)
@model.where(id: ids).each { |record| fulfill(record.id, record) }
ids.each { |id| fulfill(id, nil) unless fulfilled?(id) }
end
end
使い方はこういう感じ
code: ruby
Types::CommentType = GraphQL::ObjectType.define do
field :user, Types::UserType do
resolve -> (obj, args, ctx) {
# ここでuser_idがLoaderに蓄積されて、あとでまとめて1クエリで取得される (SELECT * FROM users WHERE id in (...))
Loaders::FindLoader.for(User).load(obj.user_id)
}
end
end
loadの戻り値はPromiseになっていて、複数段のAssociationを取ってきたい場合など複雑なケースも頭をひねると大体なんとかなる…