A paginator doing cursor-based pagination based on GORM
go get -u github.com/pilagod/gorm-cursor-paginator
Assume there is an optional query struct for paging:
type PagingQuery struct {
AfterCursor *string
BeforeCursor *string
Limit *int
Order *string
}
and a GORM model:
type Model struct {
ID uint
CreatedAt time.Time
}
You can simply build up a cursor paginator from the PagingQuery like:
import (
paginator "github.com/pilagod/gorm-cursor-paginator"
)
func InitModelPaginatorFrom(q PagingQuery) paginator.Paginator {
p := paginator.New()
p.SetKeys("CreatedAt", "ID") // [defualt: "ID"] (order of keys matters)
if q.AfterCursor != nil {
p.SetAfterCursor(*q.AfterCursor) // [default: ""]
}
if q.BeforeCursor != nil {
p.SetBeforeCursor(*q.BeforeCursor) // [default: ""]
}
if q.Limit != nil {
p.SetLimit(*q.Limit) // [default: 10]
}
if q.Order != nil {
if *q.Order == "ascending" {
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.Cursors, error) {
var models []Model
stmt := db.Where(/* ... other filters ... */)
stmt = db.Or(/* ... more other filters ... */)
// init paginator for Model
p := InitModelPaginatorFrom(q)
// use GORM-like syntax to do pagination
result := p.Paginate(stmt, &models)
if result.Error != nil {
// ...
}
// get cursors for next iteration
cursors := p.GetNextCursors()
return models, cursors, nil
}
After pagination, you can call GetNextCursors()
, which returns a Cursors
struct, to get cursors for next iteration:
type Cursors struct {
AfterCursor string
BeforeCursor string
}
That's all ! Enjoy your paging in the GORM world 🎉
© Chun-Yan Ho (pilagod), 2018-NOW
Released under the MIT License