/
mongoPagination.go
85 lines (70 loc) 路 1.74 KB
/
mongoPagination.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package utils
import (
"context"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Result struct {
Docs []bson.M
TotalDocs int64
Limit int64
Page int64
TotalPages int64
HasNextPage bool
NextPage *int64
HasPrevPage bool
PrevPage *int64
PagingCounter int64
}
func PaginateAggregate(collection *mongo.Collection, pipeline []interface{}, page, limit int64, collation *options.Collation) (result *Result, err error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*30)
defer cancel()
totalDocs, err := collection.CountDocuments(ctx, bson.D{{}})
if err != nil {
return nil, err
}
if page <= 0 {
page = 1
}
if limit <= 0 {
limit = 100
}
totalPages := (totalDocs + limit - 1) / limit
offset := (page - 1) * limit
options := options.Aggregate().SetMaxTime(time.Second * 30)
if collation != nil {
options.SetCollation(collation)
}
pipeline = append(pipeline, bson.D{{Key: "$skip", Value: offset}}, bson.D{{Key: "$limit", Value: limit}})
cursor, err := collection.Aggregate(ctx, pipeline, options)
if err != nil {
return nil, err
}
var docs []bson.M
if err := cursor.All(ctx, &docs); err != nil {
return nil, err
}
result = &Result{
Docs: docs,
TotalDocs: totalDocs,
Limit: limit,
Page: page,
TotalPages: totalPages,
HasNextPage: page < totalPages,
NextPage: nil,
HasPrevPage: page > 1,
PrevPage: nil,
PagingCounter: offset + 1,
}
if result.HasNextPage {
nextPage := result.Page + 1
result.NextPage = &nextPage
}
if page > 1 {
prevPage := page - 1
result.PrevPage = &prevPage
}
return result, nil
}