yohgo/pagination is a general purpose pagination library ideal for paginating and filtering RESTful response data.
- Go 1.8+
- Lightweight and fast
- Native Go implementation
- Supports both MSSQL and MySQL databases
Simply install the package to your $GOPATH with the go tool from shell:
$ go get github.com/yohgo/pagination
Once yohgo pagination is installed, it can be used following the steps below:
Yohgo Pagination provides a set of special URL Parameters
for the purpose of paginating and filtering the results of an API GET
requests.
Paginating Results
Yohgo Pagination enables users to easily slice results into a set of fixed size page
's as well as ordering these page
's based on any field/order combination. Yohgo pagination does so by providing the page
, limit
, order_by
, and order
parameters described below:
Argument | Type | Required? | Description | Example |
---|---|---|---|---|
page | integer | No | Specifies the current result page | ?page=1 |
Limit | integer | Yes, if page is set | Specifies the maximum no of records per page | ?page=1&limit=2 |
order_by | string | No | Sorts the records list by a particular attribute | ?order_by=name |
order | string | Yes, if order_by is set | Specifies the sorting direction | ?order_by=name&order=asc |
For example, if we have the api.awesome.com/users
endpoint that manages users, and we want to get a collection of users divided into page
's of size 10 and ordered by user name in an ascending fashion, we can do the following:
curl -X GET 'http://api.awesome.com/users?page=1&limit=10&order_by=name&order=asc'
Filtering Results
Similarly, Yohgo Pagination enables users to easily filter results through special Search Parameters
. A Search Parameter
follows the following format:
{field}__{operator}={value}
Also, multiple Search Parameter
's can be combined together using the special searchOperator
parameter which can either be AND
or OR
.
?{field1}__{operator1}={value1}&{field2}__{operator2}={value2}&searchOperator=AND
The following table shows the list of all possible operators provided by yohgo pagination:
Operator | Description | Data-types |
---|---|---|
equals | The value of the field is tested for equality against the specified value. |
numerics, strings |
notequals | The value of the field is tested for non-equality against the specified value. |
numerics, strings |
greaterthan | Checks to see whether the value of the field is greater than the specified value. |
numerics |
lessthan | Checks to see whether the value of the field is less than the specified value. |
numerics |
gthanorequals | Checks to see whether the value of the field is greater than or equal to the specified value. |
numerics |
lthanorequals | Checks to see whether the value of the field is less than or equal to the specified value. |
numerics |
startswith | Checks to see whether the value of the field starts with the specified value. |
strings |
endswith | Checks to see whether the value of the field ends with the specified value. |
strings |
contains | Checks to see whether the value of the field contains the specified value. |
strings |
after | Filters so that the results have a field value after the specified time and date. |
dates |
before | Filters so that the results have a field value before the specified time and date. |
dates |
year | Filters the results so that the year section of the field matches the specified numerical value. |
dates |
month | Filters the results so that the month section of the field matches the specified numerical value. |
dates |
day | Filters the results so that the day section of the field matches the specified numerical value. |
dates |
For example, if we have the api.awesome.com/users
endpoint that manages users, and we want to get a collection of users where user name contains the string "dav" and divided into page
's of size 10, we simply do the following:
curl -X GET 'http://api.awesome.com/users?page=1&limit=10&name__contains=dav'
Creating a pagination query is as simple as calling the NewQuery
method. The NewQuery
method take as parameter of type url.Values and returns a pagination Query
as shown the simple handler function below.
func UsersHandler(w http.ResponseWriter, req *http.Request) {
// First, creating a pagination query for the http request
query, _ := pagination.NewQuery(req.URL.Query())
// Second, passing the pagination query down the layer stack
users := UsersService.GetAll(query)
// Finally, converting the raw result into a pagination page
page, _ := pagination.NewPage(req.URL, users)
// ResolveJSON writes a json encoded page into the response (github.com/yohgo/pastry)
ResolveJSON(w, http.StatusOK, page)
}
For example, in the above snippet if req
has the following raw url api.awesome.com/users?page=1&limit=2&order_by=id&order=asc&name_contains=dav&age_greaterthan=20&searchOperator=OR
pagination will produce the following Query
struct:
query := &pagination.Query{
Page: 1,
Limit: 2,
OrderBy: "id",
Order: "asc",
Search: &pagination.Search{
SQL: "((name LIKE ?) OR (age > ?))",
Parameters: []interface{}{
"%dav%",
"20",
}
},
}
And after receiving the paginated/filtered results, yohgo pagination will use this result to produce the following pagination page page
page := &pagination.Page{
Links &pagination.Links{
Next: "api.awesome.com/users?page=2&limit=2&order_by=id&order=asc&name_contains=dav&age_greaterthan=20&searchOperator=OR",
Previous: "",
Self: "api.awesome.com/users?page=1&limit=2&order_by=id&order=asc&name_contains=dav&age_greaterthan=20&searchOperator=OR",
},
Count: 2,
Results []User{
{
Name: "David",
Age: 23
},
{
Name: "dave",
Age: 26
},
}
}
When received from the layers above, the pagination query can be used at the data access layer to dictate how the data is retrieved form the data source, thus, paginating/filtering the results . For example, the following snippet uses pagination a pagination Query
and GORM to retrieve a paginated/filtered slice of users:
func GetAllUsers(query Query) []User {
var users []User
// Retrieving a filtered slice of user using GORM
if err := repository.DB.
Where(query.Search.SQL, query.Search.Parameters...).
Order(query.GetOrder()).
Limit(query.GetLimit()).
Offset(query.GetOffset()).
Find(&users).Error; err != nil {
return nil
}
return users
}