Mike Schwörer
7413ea045d
Some checks failed
Build Docker and Deploy / Run goext test-suite (push) Failing after 1m41s
87 lines
2.8 KiB
Go
87 lines
2.8 KiB
Go
package wmo
|
|
|
|
import (
|
|
"context"
|
|
"go.mongodb.org/mongo-driver/bson"
|
|
"go.mongodb.org/mongo-driver/mongo"
|
|
ct "gogs.mikescher.com/BlackForestBytes/goext/cursortoken"
|
|
"gogs.mikescher.com/BlackForestBytes/goext/exerr"
|
|
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
|
pag "gogs.mikescher.com/BlackForestBytes/goext/pagination"
|
|
)
|
|
|
|
func (c *Coll[TData]) Paginate(ctx context.Context, filter pag.Filter, page int, limit *int) ([]TData, pag.Pagination, error) {
|
|
type totalCountResult struct {
|
|
Count int `bson:"count"`
|
|
}
|
|
|
|
if page < 0 {
|
|
page = 1
|
|
}
|
|
|
|
pipelineSort := mongo.Pipeline{}
|
|
pipelineFilter := mongo.Pipeline{}
|
|
pf1 := "_id"
|
|
pd1 := ct.SortASC
|
|
|
|
if filter != nil {
|
|
pipelineFilter = filter.FilterQuery()
|
|
pf1, pd1 = filter.Pagination()
|
|
}
|
|
|
|
if pd1 == ct.SortASC {
|
|
pipelineSort = append(pipelineSort, bson.D{{Key: "$sort", Value: bson.D{{Key: pf1, Value: +1}}}})
|
|
} else if pd1 == ct.SortDESC {
|
|
pipelineSort = append(pipelineSort, bson.D{{Key: "$sort", Value: bson.D{{Key: pf1, Value: -1}}}})
|
|
}
|
|
|
|
pipelinePaginate := mongo.Pipeline{}
|
|
if limit != nil {
|
|
pipelinePaginate = append(pipelinePaginate, bson.D{{Key: "$skip", Value: *limit * (page - 1)}})
|
|
pipelinePaginate = append(pipelinePaginate, bson.D{{Key: "$limit", Value: *limit}})
|
|
} else {
|
|
page = 1
|
|
}
|
|
|
|
pipelineCount := mongo.Pipeline{}
|
|
pipelinePaginate = append(pipelinePaginate, bson.D{{Key: "$count", Value: "count"}})
|
|
|
|
pipelineList := langext.ArrConcat(mongo.Pipeline{}, pipelineFilter, pipelinePaginate)
|
|
pipelineTotalCount := langext.ArrConcat(mongo.Pipeline{}, pipelineFilter, pipelineCount)
|
|
|
|
cursorList, err := c.coll.Aggregate(ctx, pipelineList)
|
|
if err != nil {
|
|
return nil, pag.Pagination{}, exerr.Wrap(err, "mongo-aggregation failed").Any("pipeline", pipelineList).Str("collection", c.Name()).Build()
|
|
}
|
|
|
|
entities, err := c.decodeAll(ctx, cursorList)
|
|
if err != nil {
|
|
return nil, pag.Pagination{}, exerr.Wrap(err, "failed to all-decode entities").Build()
|
|
}
|
|
|
|
cursorTotalCount, err := c.coll.Aggregate(ctx, pipelineTotalCount)
|
|
if err != nil {
|
|
return nil, pag.Pagination{}, exerr.Wrap(err, "mongo-aggregation failed").Any("pipeline", pipelineTotalCount).Str("collection", c.Name()).Build()
|
|
}
|
|
|
|
var tcRes totalCountResult
|
|
if cursorTotalCount.Next(ctx) {
|
|
err = cursorTotalCount.Decode(&tcRes)
|
|
if err != nil {
|
|
return nil, pag.Pagination{}, exerr.Wrap(err, "failed to decode mongo-aggregation $count result").Any("pipeline", pipelineTotalCount).Str("collection", c.Name()).Build()
|
|
}
|
|
} else {
|
|
tcRes.Count = 0 // no entries in DB
|
|
}
|
|
|
|
paginationObj := pag.Pagination{
|
|
Page: page,
|
|
Limit: langext.Coalesce(limit, tcRes.Count),
|
|
TotalPages: pag.CalcPaginationTotalPages(tcRes.Count, langext.Coalesce(limit, tcRes.Count)),
|
|
TotalItems: tcRes.Count,
|
|
CurrentPageCount: len(entities),
|
|
}
|
|
|
|
return entities, paginationObj, nil
|
|
}
|