graphql-ruby基于Connection的分页如何作用于ActiveRecord查询?
核心原因
你当前的Resolver中类型声明与外层字段的Connection类型不匹配,且first/after等分页参数默认由graphql-ruby的连接层自动处理,分页逻辑执行在resolve方法返回结果之后,所以你在resolve内无法直接看到参数的应用。
方案1:使用内置自动分页(推荐,适配绝大多数场景)
graphql-ruby内置的ActiveRecord Connection会自动识别分页参数,对返回的ActiveRecord Relation应用对应查询条件,你只需要修正Resolver的类型声明即可:
module Queries class PostsQuery < Queries::BaseQuery # 类型与外层字段的connection_type保持一致 type Types::PostType.connection_type, null: false def resolve # 必须添加稳定的排序规则,游标分页依赖固定排序避免结果错位 Post.order(created_at: :desc, id: :desc) end end end
这种场景下你不需要手动处理任何分页参数,gem会自动完成游标解析、条件拼接、limit限制、结果封装的全流程,你在resolve中打印posts.count得到全量计数是正常的,因为此时分页条件还未应用。
方案2:手动控制分页逻辑(适用于自定义查询场景)
如果需要自己实现分页逻辑,可以在resolve方法中显式声明接收分页参数,手动解析游标后拼接查询条件:
module Queries class PostsQuery < Queries::BaseQuery type Types::PostType.connection_type, null: false # 显式声明接收标准分页参数 def resolve(first: nil, after: nil, last: nil, before: nil, **other_args) posts = Post.order(created_at: :desc, id: :desc) # 解码after游标,默认游标格式为`模型名:主键ID` if after.present? decoded_cursor = GraphQL::Pagination::Connection.decode_node_identifier(after) last_record_id = decoded_cursor.split(":").last posts = posts.where("id < ?", last_record_id) end # 应用条数限制 posts = posts.limit(first) if first.present? posts end end end
注意事项
- 游标分页必须依赖稳定的排序规则,建议至少使用两个唯一字段组合排序(如创建时间+主键ID),避免相同排序值的记录导致分页结果重复或缺失
- 内置分页默认会自动计算总记录数,如果你需要优化性能可以通过配置关闭总计数的查询
内容的提问来源于stack exchange,提问作者yalestar
相关产品推荐
相关产品推荐

