我第一次尝试GraphQL、分页和Rails中的批加载。我需要一些人帮忙调查引擎盖下面发生的事情。我使用GraphQL::Batch
。这是我的两个Qraphql类型(精简),表示1对多(has_many,belongs_to pair in AR)关系:
module Types class GoalType < Types::BaseObject field :id, ID, null: false field :title, String field :tags_connection, Types::TagType.connection_type def tags_connection Loaders::RecordLoader.for(::Tag).load_many(object.tag_ids) end end end module Types class TagType < Types::BaseObject field :id, ID, null: false field :name, String end end
下面是查询根实现:
field :goals_connection, Types::GoalType.connection_type, null: false def goals_connection Goal.all end
到目前为止,我可以得到分页列表,并且它工作正常(好吧,我仍然对查询的数量有问题,这比imo要多,但这是另一个问题)。问题是,当我像下面这样运行查询时:
query GoalQuery { goalsConnection(first: 2) { nodes { id title tagsConnection(first: 2) { nodes { name eventsCounter } } } } }
我看到生成了以下SQL语句:
Goal Load (0.1ms) SELECT "goals".* FROM "goals" LIMIT ? OFFSET ? [["LIMIT", 2], ["OFFSET", 0]] Tag Pluck (0.1ms) SELECT "tags"."id" FROM "tags" WHERE "tags"."goal_id" = ? ORDER BY events_counter desc LIMIT ? [["goal_id", 1], ["LIMIT", 100]] Tag Pluck (0.2ms) SELECT "tags"."id" FROM "tags" WHERE "tags"."goal_id" = ? ORDER BY events_counter desc LIMIT ? [["goal_id", 2], ["LIMIT", 100]] Tag Load (0.2ms) SELECT "tags".* FROM "tags" WHERE "tags"."id" IN (?, ?, ?, ?, ?, ?, ?) [["id", 2], ["id", 1], ["id", 3], ["id", 4], ["id", 5], ["id", 6], ["id", 7]]
所以,我的困惑是这里LIMIT
的用法。Goal
上的第一个查询是根据请求的页面添加LIMIT
和OFFSET
。但是,嵌套连接正在设置一个LIMIT = 100
,这与我的页面请求没有任何关系,而且我没有在任何地方设置值100(甚至在default_max_page_size
和default_page_size
上也没有)。那么,为什么限制为100,以及如何应用页面大小?一天结束后,我得到了正确的页面,除了顶层实体之外,它都在内存中吗?
我已经更改了查询根实现以预加载连接:
field :goals_connection, Types::GoalType.connection_type, null: false def goals_connection Goal.preload(:tags) end
它去掉了额外的查询,但上面仍然有limit: 100
。我没有使用preload
的原因是我担心它无法正确应用分页限制,因为我读到你不能对预加载的关联设置约束。但是,现在即使没有预加载,我也看到类似的事情发生了。所以,也许预加载是正确的方式,除了可能我一开始没有正确实现分页?