@@ -17,16 +17,38 @@ func (c *Collection) Paginate(ctx context.Context, rawFilter any, s *usecasex.So
17
17
return nil , nil
18
18
}
19
19
20
- pFilter , pOpts , err := c .findFilter (ctx , * p , s )
20
+ pFilter , err := c .pageFilter (ctx , * p , s )
21
21
if err != nil {
22
22
return nil , rerror .ErrInternalByWithContext (ctx , err )
23
23
}
24
+
24
25
filter := rawFilter
25
26
if pFilter != nil {
26
27
filter = And (rawFilter , "" , pFilter )
27
28
}
28
29
29
- cursor , err := c .collection .Find (ctx , filter , append ([]* options.FindOptions {pOpts }, opts ... )... )
30
+ sortKey := idKey
31
+ sortOrder := 1
32
+ if s != nil && s .Key != "" {
33
+ sortKey = s .Key
34
+ if s .Reverted {
35
+ sortOrder = - 1
36
+ }
37
+ }
38
+
39
+ if p .Cursor != nil && p .Cursor .Last != nil {
40
+ sortOrder *= - 1
41
+ }
42
+
43
+ findOpts := options .Find ().
44
+ SetSort (bson.D {{Key : sortKey , Value : sortOrder }, {Key : idKey , Value : sortOrder }}).
45
+ SetLimit (limit (* p ))
46
+
47
+ if p .Offset != nil {
48
+ findOpts .SetSkip (p .Offset .Offset )
49
+ }
50
+
51
+ cursor , err := c .collection .Find (ctx , filter , append ([]* options.FindOptions {findOpts }, opts ... )... )
30
52
if err != nil {
31
53
return nil , rerror .ErrInternalByWithContext (ctx , fmt .Errorf ("failed to find: %w" , err ))
32
54
}
@@ -46,6 +68,7 @@ func (c *Collection) Paginate(ctx context.Context, rawFilter any, s *usecasex.So
46
68
47
69
if p .Cursor != nil && p .Cursor .Last != nil {
48
70
reverse (items )
71
+ startCursor , endCursor = endCursor , startCursor
49
72
}
50
73
51
74
for _ , item := range items {
@@ -59,7 +82,6 @@ func (c *Collection) Paginate(ctx context.Context, rawFilter any, s *usecasex.So
59
82
return usecasex .NewPageInfo (count , startCursor , endCursor , hasNextPage , hasPreviousPage ), nil
60
83
}
61
84
62
-
63
85
func (c * Collection ) PaginateAggregation (ctx context.Context , pipeline []any , s * usecasex.Sort , p * usecasex.Pagination , consumer Consumer , opts ... * options.AggregateOptions ) (* usecasex.PageInfo , error ) {
64
86
if p == nil || p .Cursor == nil && p .Offset == nil {
65
87
return nil , nil
@@ -212,56 +234,77 @@ func aggregateOptionsFromPagination(_ usecasex.Pagination, _ *usecasex.Sort) *op
212
234
return options .Aggregate ().SetAllowDiskUse (true ).SetCollation (& collation )
213
235
}
214
236
215
- func (c * Collection ) pageFilter (ctx context.Context , p usecasex.Pagination , s * usecasex.Sort ) (any , error ) {
237
+ func (c * Collection ) pageFilter (ctx context.Context , p usecasex.Pagination , s * usecasex.Sort ) (bson. M , error ) {
216
238
if p .Cursor == nil {
217
239
return nil , nil
218
240
}
219
241
242
+ var filter bson.M
243
+ sortKey := idKey
244
+ sortOrder := 1
245
+
246
+ if s != nil && s .Key != "" {
247
+ sortKey = s .Key
248
+ if s .Reverted {
249
+ sortOrder = - 1
250
+ }
251
+ }
252
+
253
+ var cursor * usecasex.Cursor
220
254
var op string
221
- var cur * usecasex.Cursor
222
255
223
- if p .Cursor .First != nil {
256
+ if p .Cursor .After != nil {
257
+ cursor = p .Cursor .After
224
258
op = "$gt"
225
- cur = p .Cursor .After
226
- } else if p .Cursor .Last != nil {
259
+ } else if p .Cursor .Before != nil {
260
+ cursor = p .Cursor .Before
227
261
op = "$lt"
228
- cur = p .Cursor .Before
229
- } else {
230
- return nil , errors .New ("neither first nor last are set" )
231
262
}
232
- if cur == nil {
233
- return nil , nil
234
- }
235
-
236
- var sortKey * string
237
- if s != nil {
238
- sortKey = & s .Key
239
- }
240
- var paginationFilter bson.M
241
- if sortKey == nil || * sortKey == "" {
242
- paginationFilter = bson.M {idKey : bson.M {op : * cur }}
243
- } else {
244
- var cursorDoc bson.M
245
- if err := c .collection .FindOne (ctx , bson.M {idKey : * cur }).Decode (& cursorDoc ); err != nil {
246
- return nil , fmt .Errorf ("failed to find cursor element" )
247
- }
248
263
249
- if cursorDoc [* sortKey ] == nil {
250
- return nil , fmt .Errorf ("invalied sort key" )
264
+ if cursor != nil {
265
+ cursorDoc , err := c .getCursorDocument (ctx , * cursor )
266
+ if err != nil {
267
+ return nil , err
251
268
}
252
269
253
- paginationFilter = bson.M {
270
+ filter = bson.M {
254
271
"$or" : []bson.M {
255
- {* sortKey : bson.M {op : cursorDoc [* sortKey ]}},
272
+ {sortKey : bson.M {op : cursorDoc [sortKey ]}},
256
273
{
257
- * sortKey : cursorDoc [* sortKey ],
258
- idKey : bson.M {op : * cur },
274
+ sortKey : cursorDoc [sortKey ],
275
+ idKey : bson.M {op : cursorDoc [ idKey ] },
259
276
},
260
277
},
261
278
}
279
+
280
+ if sortOrder == - 1 {
281
+ if op == "$gt" {
282
+ op = "$lt"
283
+ } else {
284
+ op = "$gt"
285
+ }
286
+ filter = bson.M {
287
+ "$or" : []bson.M {
288
+ {sortKey : bson.M {op : cursorDoc [sortKey ]}},
289
+ {
290
+ sortKey : cursorDoc [sortKey ],
291
+ idKey : bson.M {op : cursorDoc [idKey ]},
292
+ },
293
+ },
294
+ }
295
+ }
262
296
}
263
297
264
- return paginationFilter , nil
298
+ return filter , nil
299
+ }
300
+
301
+ func (c * Collection ) getCursorDocument (ctx context.Context , cursor usecasex.Cursor ) (bson.M , error ) {
302
+ var cursorDoc bson.M
303
+ err := c .collection .FindOne (ctx , bson.M {idKey : cursor }).Decode (& cursorDoc )
304
+ if err != nil {
305
+ return nil , fmt .Errorf ("failed to find cursor element: %w" , err )
306
+ }
307
+ return cursorDoc , nil
265
308
}
266
309
267
310
func sortFilter (p usecasex.Pagination , s * usecasex.Sort ) bson.D {
0 commit comments