Documentation
¶
Overview ¶
Package pagination provides building blocks for cursor-free, offset-based pagination with filtering and sorting, designed to work seamlessly with GORM.
Overview ¶
The package exposes three concerns:
- Page / Result request params and response envelope
- Filter / Sort builders fluent APIs to compose WHERE and ORDER BY clauses
- Scope a GORM scope that wires everything together in a single call
Quick start ¶
// 1. Embed Page in your request DTO so it binds from query-string params.
type ListReq struct {
pagination.Page
Status string `form:"status"`
}
// 2. Build filters and sorts.
filters := pagination.NewFilterBuilder().
WhereIf(req.Status != "", "status", pagination.Eq, req.Status).
Build()
sorts := pagination.ParseSort(req.Sort) // "created_at desc,amount asc"
if len(sorts) == 0 {
sorts = pagination.NewSortBuilder().
OrderBy("created_at", pagination.Desc).
Build()
}
// 3. Assemble a Query (normalises the page automatically).
query := pagination.NewQuery(req.Page, filters, sorts)
// 4. Execute with GORM.
var rows []MyModel
var total int64
db.Model(&MyModel{}).
Scopes(pagination.Scope(query, &total)).
Find(&rows)
// 5. Build the response envelope.
result := pagination.NewResult(rows, int(total), query.Page)
Defaults and limits ¶
When the caller omits pagination params, Page.Normalize applies safe defaults:
- page defaults to 1 (DefPage)
- per_page defaults to 20 (DefPerPage)
- per_page is capped at 100 (MaxPerPage)
Supported filter operators ¶
pagination.Eq // = pagination.Neq // <> pagination.Gt // > pagination.Gte // >= pagination.Lt // < pagination.Lte // <= pagination.Like // LIKE (value is automatically wrapped with %) pagination.ILike // ILIKE (value is automatically wrapped with %) pagination.In // IN (?) pagination.NotIn // NOT IN (?) pagination.IsNull // IS NULL pagination.IsNotNull // IS NOT NULL
Index ¶
Constants ¶
View Source
const ( DefPage = 1 DefPerPage = 20 MaxPerPage = 100 )
Variables ¶
This section is empty.
Functions ¶
Types ¶
type FilterBuilder ¶
type FilterBuilder struct {
// contains filtered or unexported fields
}
FilterBuilder provides a fluent API to build []Filter
filters := paginator.NewFilterBuilder()
Where("status", paginator.Eq, "active")
Where("amount", paginator.Gte, 100)
Build()
func NewFilterBuilder ¶
func NewFilterBuilder() *FilterBuilder
func (*FilterBuilder) Build ¶
func (b *FilterBuilder) Build() []Filter
func (*FilterBuilder) Where ¶
func (b *FilterBuilder) Where(field string, op Operator, value any) *FilterBuilder
func (*FilterBuilder) WhereIf ¶
func (b *FilterBuilder) WhereIf(cond bool, field string, op Operator, value any) *FilterBuilder
type Page ¶
type Page struct {
Number int `json:"page" gorm:"page"`
PerPage int `json:"per_page" gorm:"per_page"`
}
Page holds pagination request params.
type Result ¶
type Result[T any] struct { Data []T `json:"data"` Total int `json:"total"` Page int `json:"page"` PerPage int `json:"per_page"` TotalPages int `json:"total_pages"` HasNext bool `json:"has_next"` HasPrev bool `json:"has_prev"` }
Result is the generic paginated response
type Sort ¶
type Sort struct {
Field string
Direction SortDirection
}
Sort represents a single ORDER BY clause
type SortBuilder ¶
type SortBuilder struct {
// contains filtered or unexported fields
}
SortBuilder provides a fluent API to build []Sort
sorts := paginator.NewSortBuilder()
OrderBy("created_at", paginator.Desc)
Build()
func NewSortBuilder ¶
func NewSortBuilder() *SortBuilder
func (*SortBuilder) Build ¶
func (b *SortBuilder) Build() []Sort
func (*SortBuilder) OrderBy ¶
func (b *SortBuilder) OrderBy(field string, dir SortDirection) *SortBuilder
type SortDirection ¶
type SortDirection string
SortDirection for ORDER BY clauses
const ( Asc SortDirection = "ASC" Desc SortDirection = "DESC" )
Click to show internal directories.
Click to hide internal directories.