Created
October 12, 2022 07:41
-
-
Save cemremengu/f7e66a61fe3dfaf6dcdb443dff1df1f4 to your computer and use it in GitHub Desktop.
paginator.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package paginator | |
import ( | |
"context" | |
"database/sql" | |
"errors" | |
"github.com/uptrace/bun" | |
"math" | |
) | |
// TODO: make sort a list | |
type Pagination struct { | |
Page int `json:"page"` | |
Size int `json:"size"` | |
Sort Sort `json:"sort"` | |
} | |
type Sort struct { | |
Key string `json:"key"` | |
Order string `json:"order"` | |
} | |
func (s *Sort) String() string { | |
return s.Key + " " + s.Order | |
} | |
func (s *Sort) Valid() bool { | |
return s.Key != "" && s.Order != "" | |
} | |
type Paginator[T any] struct { | |
Params Pagination | |
Query *bun.SelectQuery | |
} | |
type Page[T any] struct { | |
Content []T `json:"content"` | |
TotalElements int `json:"totalElements"` | |
TotalPages int `json:"totalPages"` | |
Number int `json:"number"` | |
Size int `json:"size"` | |
NumberOfElements int `json:"numberOfElements"` | |
} | |
// Find applies pagination with given parameters | |
// See https://github.com/dmitryburov/gorm-paginator | |
// https://github.com/hellokaton/gorm-paginator | |
func (p *Paginator[T]) Find() (Page[T], error) { | |
var ( | |
q = p.Query | |
done = make(chan int, 1) | |
defPage = 1 | |
defLimit = 20 | |
count int | |
offset int | |
result []T | |
) | |
// get all counts | |
go getCounts(q, done) | |
// limit | |
if p.Params.Size == 0 { | |
p.Params.Size = defLimit | |
} | |
// page | |
if p.Params.Page < 1 { | |
p.Params.Page = defPage | |
} else if p.Params.Page > 1 { | |
offset = (p.Params.Page - 1) * p.Params.Size | |
} | |
// sort | |
//if len(p.Paging.OrderBy) > 0 { | |
// for _, o := range p.Paging.OrderBy { | |
// db = db.Order(o) | |
// } | |
//} else { | |
// str := "id desc" | |
// p.Paging.OrderBy = append(p.Paging.OrderBy, str) | |
//} | |
if p.Params.Sort.Valid() { | |
q = q.Order(p.Params.Sort.String()) | |
} | |
err := q.Limit(p.Params.Size).Offset(offset).Scan(context.TODO(), &result) | |
if err != nil && !errors.Is(err, sql.ErrNoRows) { | |
return Page[T]{}, err | |
} | |
count = <-done | |
// total pages | |
total := int(math.Ceil(float64(count) / float64(p.Params.Size))) | |
// construct pagination | |
page := Page[T]{ | |
Content: result, | |
TotalElements: count, | |
TotalPages: total, | |
Number: p.Params.Page, | |
Size: p.Params.Size, | |
NumberOfElements: len(result), | |
} | |
//// prev page | |
//if p.Page > 1 { | |
// paginator.PrevPage = p.Paging.Page - 1 | |
//} | |
//// next page | |
//if p.Page != paginator.TotalPage { | |
// paginator.NextPage = p.Paging.Page + 1 | |
//} | |
return page, nil | |
} | |
func getCounts(q *bun.SelectQuery, done chan int) { | |
c, _ := q.Count(context.TODO()) | |
done <- c | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment