-
-
Notifications
You must be signed in to change notification settings - Fork 17
Pagination
What's a keyset pagination: http://use-the-index-luke.com/no-offset.
Take a model named Post as an example. A data type PostPage will be generated for paginating:
type PostPage struct {
WhereString string
WhereParams []interface{}
Order map[string]string
FirstId int64
LastId int64
PageNum int
PerPage int
TotalPages int
TotalItems int64
}And meanwhile generated three methods Current, Next and Previous:
// Current get the current page of PostPage object for pagination
func (_p *PostPage) Current() ([]Post, error)
// Current get the next page of PostPage object for pagination
func (_p *PostPage) Next() ([]Post, error)
// Current get the previous page of PostPage object for pagination
func (_p *PostPage) Previous() ([]Post, error)You can init a PostPage at first:
pp := &PostPage{Order: map[string]string{"id": "desc"}, PerPage: 5}Then get the first page:
ps, err := pp.Current()Then next page:
ps, err = pp.Next()Or back to previous page:
ps, err = pp.Previous()Show the current page number:
fmt.Println(pp.PageNum)Show total pages and total count:
fmt.Println(pp.TotalPages)
fmt.Println(pp.TotalItems)You can add a where clause with parameters as a filter when init a PostPage object:
pp := &PostPage{
WhereString: "title LIKE ? AND hits > ?",
WhereParams: []interface{}{"%go-on-rails%", 200},
Order: map[string]string{"id": "desc"},
PerPage: 5}Here the WhereString is a ? binding with WhereParams correspondingly.
All above is making a pagination object in the Model level, now we show how to make it work from the View to the Controller(a handler), and then call the methods of the object.
For example we GET an index page and pass three parameters:
- pagination: previous / current / next, optional, it will be
currentif omited - first_id: the first ID in the page, optional, it will be 0 if omited
- last_id: the last ID in the page, optional, it will be 0 if omited
In our Controller, we will do some check and then get the right page:
// for example, we use the Gin framework, and this's in a function named IndexHander
function IndexHandler(c *gin.Context) {
pagination := c.Param("pagination")
firstId, _ := strconv.ParseInt(c.Param("first_id"), 10, 64)
lastId, _ := strconv.ParseInt(c.Param("last_id"), 10, 64)
pp := &PostPage{
WhereString: "title LIKE ? AND hits > ?",
WhereParams: []interface{}{"%go-on-rails%", 200},
Order: map[string]string{"id": "desc"},
PerPage: 5,
FirstId: firstId,
LastId: lastId}
ps := []Post
switch pagination {
case "previous":
ps, _ = pp.Previous()
case "next":
ps, _ = pp.Next()
default:
ps, _ = pp.Current()
}
c.JSON(200, gin.H{
"status": "success"
"data": ps
})
}In the View, take the GET action for example, the relative path will be:
/posts?pagination=(previous|current|next)&first_id=A_NUM&last_id=A_NUM
Other actions like POST are similiar to pass the three parameters: pagination, first_id and last_id.