Cursor-based go paginator
APACHE-2.0 License
An efficient go data cursor-based paginator.
go get github.com/raphaelvigee/go-paginate
A lot of articles on the internet summarize very well the benefits of cursor-based pagination, but here are the highlights:
OFFSET
/LIMIT
-based pagination doesn't scale well for large datasetsIt does have an issue, it is hard to implement, that's why go-paginate
exists :)
gorm:
ORDER BY id ASC, name DESC
)Implement your own: See driver.Driver and base.Driver
Can't find what you are looking for? Open an issue!
gorm
Errors omitted for brevity
Create the paginator, defining the criteria (columns and ordering):
pg := paginator.New(paginator.Options{
Driver: gorm.New(gorm.Options{
Columns: []gorm.Column{
{
Name: "created_at",
},
},
}),
})
Create the cursor instance, most likely from the request (in the initial request, the cursor is an empty string):
c, err := pg.Cursor("<cursor from client>", cursor.After, 2)
Create a transaction with appropriate filtering etc and request the pagination info:
tx := db.Model(&User{}).Where(...)
page, err := pg.Paginate(c, tx)
// That should be sent back to the client along with the data
fmt.Println(page.PageInfo.HasPreviousPage)
fmt.Println(page.PageInfo.HasNextPage)
fmt.Println(page.PageInfo.StartCursor)
fmt.Println(page.PageInfo.EndCursor)
Retrieve the underlying data for the page:
var users []User
err := page.Query(&users)
A full working example can be found in _examples/gorm.
By default, the cursor will be marshalled through msgpack
for size concerns, and base64
for portability.
One can choose to do differently (for example encrypting them...), see the implementation of cursor.MsgPack
and cursor.Base64
.
pg := paginator.New(paginator.Options{
...
CursorMarshaller: cursor.Chain(cursor.MsgPack(), cursor.Base64(base64.StdEncoding))
})
TAG=v0.0.1 make tag