ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

在 Ruby GraphQL 服务中实现 limit-offset 分页:graphql-ruby 与 SearchObject 实战指南

在 Ruby GraphQL 服务中实现 limit-offset 分页:graphql-ruby 与 SearchObject 实战指南 【免费下载链接】howtographqlThe Fullstack Tutorial for GraphQL项目地址https://gitcode.com/gh_mirrors/ho/howtographql点击查看免费下载本篇指南聚焦 howtographql 仓库中 Ruby / Rails 后端教程的核心章节——在 content/backend/graphql-ruby/8-pagination.md 中你将基于已有的 Hackernews 风格的allLinks查询为 GraphQL API 添加limit-offset 分页通过在 schema 中引入skip与first两个查询参数让客户端按需获取一小批链接并逐页浏览更早的内容。读完本文你将掌握在 graphql-ruby 项目中基于 SearchObject::Plugin::GraphQL 的 Resolver 模型把LIMIT/OFFSET语义映射到 GraphQL 参数层的完整实现路径并了解它与 Relay 游标分页Connections的本质区别及适用前提。为什么 Hackernews 需要分页随着用户不断提交链接把所有历史上发布过的链接一次性全部拉取回来很快就会变得太多不仅对客户端毫无用处还会造成巨大的网络传输与内存开销。更合理的做法是每次只展示少量链接并允许用户通过翻页浏览更早的内容。分页的核心价值在于把数据量的决定权交给客户端客户端可以根据自己的屏幕尺寸、性能与交互场景主动声明本次请求需要多少条记录、从哪个位置开始取。这正是 content/backend/graphql-ruby/0-introduction.md 中Schema-Driven Development所强调的契约精神——schema 是前后端约定的契约分页参数的加入就是对这份契约的扩展前端可以据此并行开发而无需等待后端完成。本教程实现的分页方式称为limit-offset 分页。请注意这种方式不适用于前端使用 Relay 的场景因为 Relay 要求基于connections连接概念实现游标式分页。关于分页的更多背景可参考 GraphQL 官方文档的 Pagination 章节。连接与 Relay 规范的其余部分可参考 Relay 官方文档。目标 Schema向allLinks注入skip与first分页的第一步是定义 schema。我们希望在现有的allLinks查询上追加两个参数得到如下形态type Query { allLinks(filter: LinkFilter, skip: Int, first: Int): [Link!]! }first返回前n条记录对应 SQL 的LIMIT nskip跳过前n条记录后再返回对应 SQL 的OFFSET n。LinkFilter是 content/backend/graphql-ruby/7-filtering.md 中定义的输入类型用于对链接进行description_contains/url_contains以及OR分支组合过滤。skip与first均为可选的Int类型——不传时表示不限制这与原文档及LinksSearchResolver 的option声明保持一致。在LinksSearchResolver 中接入分页参数allLinks查询由Resolvers::LinksSearch这一 SearchObject Resolver 承担解析工作见 content/backend/graphql-ruby/7-filtering.md。分页参数正是通过它的option机制注册进去的。更新app/graphql/resolvers/links_search.rbrequire search_object require search_object/plugin/graphql class Resolvers::LinksSearch # ...code option :filter, type: LinkFilter, with: :apply_filter option :first, type: types.Int, with: :apply_first option :skip, type: types.Int, with: :apply_skip def apply_first(scope, value) scope.limit(value) end def apply_skip(scope, value) scope.offset(value) end # ...code end改动完成SearchObject 的option机制是如何工作的从源码结构看SearchObject 的option声明做了三件事注册参数option :first, type: types.Int把first注册为一个 GraphQL 参数类型映射为Int指定处理函数with: :apply_first告诉 SearchObject当客户端传入该参数时调用对应的方法来加工当前的查询 scope链式作用apply_first/apply_skip接收(scope, value)在 ActiveRecord 关系上链式调用limit/offset与过滤、排序等其他 option 的处理结果自然串联共同收窄最终的查询集。由于scope { Link.all }是搜索的起点见 content/backend/graphql-ruby/7-filtering.md当客户端同时传入filter、skip、first时执行顺序为先按LinkFilter条件过滤得到子集再offset(skip)跳过前面的记录最后limit(first)截取返回数量。这种以 scope 为管道的组合式处理正是 SearchObject 相比手写 Resolver 更利于长期维护的原因——后续每新增一个查询维度只需追加一个option与一个apply_*方法。与QueryType的接线在 content/backend/graphql-ruby/7-filtering.md 中QueryType已经通过 resolver 方式挂载了all_links字段module Types class QueryType BaseObject field :all_links, resolver: Resolvers::LinksSearch end end采用resolver:挂载后schema 中字段的返回类型、参数集合均来自LinksSearch自身的声明type types[Types::LinkType]加上各个option。因此无需修改QueryTypeskip与first便会自动出现在 GraphiQL 的字段文档与 Introsepction 结果中与目标 schema 完全吻合。这正是 content/backend/graphql-ruby/2-queries.md 中所讲的两种字段解析方式之一把解析逻辑封装进 GraphQL::Schema::Resolver比在类型上写同名方法更利于复用与测试。在 GraphiQL 中验证分页启动 Rails 服务后打开浏览器访问http://localhost:3000/graphiql即可用如下查询验证query { allLinks(skip: 2, first: 3) { id url description } }该查询跳过前 2 条、只取接下来的 3 条链接。若省略skip/first则与之前的allLinks行为一致返回全部链接——参数的可选性保证了向后兼容。若first传入0或负数limit/offset的语义需要结合具体数据库实现确认边界行为因此建议客户端只传正整数。分页的验证建议结合已有测试体系在 content/backend/graphql-ruby/7-filtering.md 中展示了针对LinksSearch的单元测试test/graphql/resolvers/links_search_test.rb通过::Resolvers::LinksSearch.call(nil, args, nil)直接调用 Resolver 并断言返回结果。你可以沿用同样的模式为first/skip编写用例例如创建 4 条链接后断言find(skip: 1, first: 2)只返回中间两条。执行测试的命令为bundle exec rails testlimit-offset 与 Relay 游标分页的取舍本教程选择 limit-offset 分页有其明确的使用前提与边界维度limit-offset 分页Relay Connections游标分页参数firstskipfirst/after游标实现成本低直接映射 SQLLIMIT/OFFSET较高需要封装edges/node/cursor结构前端配合任意客户端需要 Relay 或支持 Connections 规范的客户端大数据量下的跳页OFFSET越大扫描开销越高基于游标可稳定定位本仓库适用范围✅ 本教程graphql-ruby 后端前端教程中的 react-relay 路径对应地本仓库的其他后端教程也采用了同样的 limit-offset 思路例如 content/backend/graphql-python/8-pagination.md 用 Python 切片qs[skip:]/qs[:first]实现content/backend/graphql-java/10-pagination.md 用 MongoDB 的skip().limit()实现。可见以firstskip两个参数收窄查询结果是 GraphQL 服务端分页的通用实践与具体语言无关。选择何种方案取决于你的前端是否依赖 Relay 以及数据规模预期。小结与后续方向至此allLinks查询同时具备了过滤filter与分页skip、first能力一次查询即可完成按条件筛选 分页取数的组合需求。本教程的完整工程与更多改进可在 howtographql 系列的 Ruby 示例工程中查阅其教程收尾见 content/backend/graphql-ruby/9-summary.md。值得留意的进阶方向总条数统计分页 UI 往往还需要总共有多少条信息可在meta/structure/ruby.md中看到_allLinksMeta: _QueryMeta!含count字段的设计参考即额外暴露一个元数据查询用于返回计数排序meta/structure/ruby.md中还预留了orderBy: LinkOrderBy如createdAt_ASC/createdAt_DESC可按同样方式注册为option游标化升级若未来需要对接 Relay 前端可将 limit-offset 升级为基于 id 或创建时间的游标分页。赞分享【免费下载链接】howtographqlThe Fullstack Tutorial for GraphQL项目地址https://gitcode.com/gh_mirrors/ho/howtographql点击查看免费下载相关推荐Gatsby 分页实现指南基于 GraphQL 的 limit/skip 分页实战Gatsby 分页实现指南基于 GraphQL 的 limit/skip 分页实战 导读随着博客文章、商品列表等内容型页面的不断增长单页列表会变得越来越长前端静态站点Web框架掌握GORM排序与分页Order/Limit/Offset终极实战指南掌握GORM排序与分页Order/Limit/Offset终极实战指南 GORM是Golang生态中一款开发者友好的ORM库提供了简洁直观的API来处理数据后端数据库ORMAuto Remove Torrents配置文件详解打造个性化种子清理策略Auto Remove Torrents配置文件详解打造个性化种子清理策略 Auto Remove Torrents是一款强大的种子自动管理工具能够根据用户上一篇Dify工作流开发实战从零构建企业级AI应用的完整指南下一篇CANN ops-math FloorDiv 算子深度解析向下取整除法的 NPU 实现与 aclnn 调用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表