{"id":16701921,"url":"https://github.com/soranoba/pageboy","last_synced_at":"2025-08-24T00:12:02.885Z","repository":{"id":43486149,"uuid":"261231323","full_name":"soranoba/pageboy","owner":"soranoba","description":"A SQL pagination library for golang with GORM.","archived":false,"fork":false,"pushed_at":"2023-02-03T05:11:58.000Z","size":169,"stargazers_count":9,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T05:36:06.535Z","etag":null,"topics":["golang","gorm","pagination","sql"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/soranoba.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["soranoba"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://paypal.me/soranoba"]}},"created_at":"2020-05-04T16:01:18.000Z","updated_at":"2024-12-31T11:52:47.000Z","dependencies_parsed_at":"2023-02-18T03:45:48.276Z","dependency_job_id":null,"html_url":"https://github.com/soranoba/pageboy","commit_stats":null,"previous_names":["soranoba/magion"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soranoba%2Fpageboy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soranoba%2Fpageboy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soranoba%2Fpageboy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/soranoba%2Fpageboy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/soranoba","download_url":"https://codeload.github.com/soranoba/pageboy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248155436,"owners_count":21056638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["golang","gorm","pagination","sql"],"created_at":"2024-10-12T18:46:10.949Z","updated_at":"2025-04-10T04:21:24.331Z","avatar_url":"https://github.com/soranoba.png","language":"Go","funding_links":["https://github.com/sponsors/soranoba","https://paypal.me/soranoba"],"categories":[],"sub_categories":[],"readme":"pageboy\n==========\n[![CircleCI](https://circleci.com/gh/soranoba/pageboy.svg?style=svg\u0026circle-token=977b6c270d30867fe12a0e65d34f8adbb3d7d7f2)](https://circleci.com/gh/soranoba/pageboy)\n[![Go Report Card](https://goreportcard.com/badge/github.com/soranoba/pageboy)](https://goreportcard.com/report/github.com/soranoba/pageboy)\n[![PkgGoDev](https://pkg.go.dev/badge/github.com/soranoba/pageboy/v4)](https://pkg.go.dev/github.com/soranoba/pageboy/v4)\n\n`pageboy` is a pagination library with [GORM v2](https://github.com/go-gorm/gorm).\n\n## Overviews\n\n- 💪　Support both of before/after (Cursor) and page/per (Pager) DB pagination.\n- 🤗　Accept human readable queries.\n  - Like them: `?page=1\u0026per_page=2` and `?before=1585706584\u0026limit=10`\n  - We can also customize it if needed.\n- 💖　We can write smart code using GORM scopes.\n- 👌　Supports all DB engine officialy supported by GORM.\n  - MySQL, PostgreSQL, SQLite, SQL Server\n\n## Installation\n\nTo install it, run:\n\n```bash\ngo get -u github.com/soranoba/pageboy/v4\n```\n\n## Usage\n\n### Cursor\n\nCursor can be used to indicate a range that is after or before that value.\u003cbr\u003e\nIt can sort using by time or integer.\u003cbr\u003e\nFor example, when we sort using CreatedAt and ID, it can prevent duplicate values from occurring.\n\n#### Query Formats\n\n- Simple numbers\n  - `https://example.com/api/users?before=1\u0026limit=10`\n- Unix Timestamp in seconds\n  - `https://example.com/api/users?before=1585706584\u0026limit=10`\n- Unix Timestamp in milliseconds (Depends on settings on your database)\n  - `https://example.com/api/users?before=1585706584.25\u0026limit=10`\n- Unix Timestamp and Sub-Element (e.g. ID)\n  - `https://example.com/api/users?before=1585706584.25_20\u0026limit=10`\n\n#### Index Settings\n\nYou should create an index when using a Cursor.\u003cbr\u003e\nExample using CreatedAt and ID for sorting:\n\n```sql\nCREATE INDEX created_at_id ON users (created_at DESC, id DESC);\n```\n\n#### Usage in Codes\n\n```go\ndb, _ := gorm.Open(sqlite.Open(\"test.db\"), \u0026gorm.Config{})\n// Please execute it only once immediately after opening DB.\npageboy.RegisterCallbacks(db)\n```\n\n```go\ntype UsersRequest struct {\n\tpageboy.Cursor\n}\n\nfunc getUsers(ctx echo.Context) error {\n\t// Set to Default Limit\n\treq := \u0026UsersRequest{Cursor: pageboy.Cursor{Limit: 10}}\n\t// Read from query or body\n\tif err := ctx.Bind(req); err != nil {\n\t\treturn err\n\t}\n\t// Validation\n\tif err := req.Validate(); err != nil {\n\t\treturn err\n\t}\n\t// Read from DB\n\tvar users []*User\n\tif err := db.Scopes(req.Cursor.Paginate(\"CreatedAt\", \"ID\").Order(\"DESC\", \"DESC\").Scope()).Find(\u0026users).Error; err != nil {\n\t\treturn err\n\t}\n}\n```\n\n#### NULLS FIRST / NULLS LAST\n\nPostgresSQL can accept NULLS FIRST or NULLS LAST for index.\u003cbr\u003e\nIn that case, it can use the index by adding NULLS FIRST or NULLS LAST in Order.\n\nIt is not supported other engines because they cannot accept these for index.\n\n```go\ncursor.Paginate(\"CreatedAt\", \"UpdatedAt\").Order(\"DESC NULLS LAST\", \"ASC NULLS FIRST\").Scope()\n```\n\n### Pager\n\nPager can be used to indicate a range that is specified a page size and a page number.\n\n#### Query Formats\n\nIt includes a page which is 1-Based number, and per_page.\n\n- `https://example.com/users?page=1\u0026per_page=10`\n\n#### Usage in Codes\n\n```go\ndb, _ := gorm.Open(sqlite.Open(\"test.db\"), \u0026gorm.Config{})\n// Please execute it only once immediately after opening DB.\npageboy.RegisterCallbacks(db)\n```\n\n```go\ntype UsersRequest struct {\n\tpageboy.Pager\n}\n\nfunc getUsers(ctx echo.Context) error {\n\t// Set to Default\n\treq := \u0026UsersRequest{Pager: pageboy.Pager{Page: 1, PerPage: 10}}\n\t// Read from query or body\n\tif err := ctx.Bind(req); err != nil {\n\t\treturn err\n\t}\n\t// Validation\n\tif err := req.Validate(); err != nil {\n\t\treturn err\n\t}\n\t// Read from DB\n\tvar users []*User\n\tif err := db.Scopes(req.Pager.Scope()).Order(\"id ASC\").Find(\u0026users).Error; err != nil {\n\t\treturn err\n\t}\n}\n```\n\n### Attentions\n\nThis library is only available for the kind of functions that the [Query callback](https://pkg.go.dev/gorm.io/gorm@v1.21.8/callbacks#Query) is executed on.\u003cbr\u003e\nThat is, it cannot be used with [Row](https://pkg.go.dev/gorm.io/gorm@v1.21.8#DB.Row) or [Scan](https://pkg.go.dev/gorm.io/gorm@v1.21.8#DB.Scan) \u003cbr\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoranoba%2Fpageboy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsoranoba%2Fpageboy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsoranoba%2Fpageboy/lists"}