A paginator doing cursor-based pagination based on GORM
go get -u github.com/pilagod/gorm-cursor-paginator
Assume there is an query struct for paging:
type PagingQuery struct {
Cursor paginator.Cursor
Limit *int
Order *string
}
and a GORM model:
type Model struct {
ID int
CreatedAt time.Time
}
You can simply build up a new cursor paginator from the PagingQuery like:
import (
paginator "github.com/pilagod/gorm-cursor-paginator"
)
func GetModelPaginator(q PagingQuery) *paginator.Paginator {
p := paginator.New()
p.SetKeys("CreatedAt", "ID") // [defualt: "ID"] (supports multiple keys, and order of keys matters)
if q.Cursor.After != nil {
p.SetAfterCursor(*q.Cursor.After) // [default: nil]
}
if q.Cursor.Before != nil {
p.SetBeforeCursor(*q.Cursor.Before) // [default: nil]
}
if q.Limit != nil {
p.SetLimit(*q.Limit) // [default: 10]
}
if q.Order != nil && *q.Order == "asc" {
p.SetOrder(paginator.ASC) // [default: paginator.DESC]
}
return p
}
Then you can start to do pagination easily with GORM:
func Find(db *gorm.DB, q PagingQuery) ([]Model, paginator.Cursor, error) {
var models []Model
stmt := db.Where(/* ... other filters ... */)
stmt = db.Or(/* ... more other filters ... */)
// get paginator for Model
p := GetModelPaginator(q)
// use GORM-like syntax to do pagination
result := p.Paginate(stmt, &models)
if result.Error != nil {
// ...
}
// get cursor for next iteration
cursor := p.GetNextCursor()
return models, cursor, nil
}
After paginating, you can call GetNextCursor()
, which returns a Cursor
struct containing cursor for next iteration:
type Cursor struct {
After *string `json:"after"`
Before *string `json:"before"`
}
That's all ! Enjoy your paging in the GORM world 🎉
© Chun-Yan Ho (pilagod), 2018-NOW
Released under the MIT License