Skip to content

Commit 4fcdd23

Browse files
authored
fix(server): enable original key filter (#57)
* enable original key filter * add PaginateProject method * fix lint --------- Co-authored-by: tomokazu tantaka <[email protected]>
1 parent a7f7b61 commit 4fcdd23

File tree

3 files changed

+471
-58
lines changed

3 files changed

+471
-58
lines changed

mongox/pagination.go

Lines changed: 82 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -27,64 +27,7 @@ func (c *Collection) Paginate(ctx context.Context, rawFilter any, s *usecasex.So
2727
filter = And(rawFilter, "", pFilter)
2828
}
2929

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-
sort := bson.D{{Key: sortKey, Value: sortOrder}}
44-
if sortKey != idKey {
45-
sort = append(sort, bson.E{Key: idKey, Value: sortOrder})
46-
}
47-
48-
findOpts := options.Find().
49-
SetSort(sort).
50-
SetLimit(limit(*p))
51-
52-
if p.Offset != nil {
53-
findOpts.SetSkip(p.Offset.Offset)
54-
}
55-
56-
cursor, err := c.collection.Find(ctx, filter, append([]*options.FindOptions{findOpts}, opts...)...)
57-
if err != nil {
58-
return nil, rerror.ErrInternalByWithContext(ctx, fmt.Errorf("failed to find: %w", err))
59-
}
60-
defer func() {
61-
_ = cursor.Close(ctx)
62-
}()
63-
64-
count, err := c.collection.CountDocuments(ctx, rawFilter)
65-
if err != nil {
66-
return nil, rerror.ErrInternalByWithContext(ctx, fmt.Errorf("failed to count: %w", err))
67-
}
68-
69-
items, startCursor, endCursor, hasMore, err := consume(ctx, cursor, limit(*p))
70-
if err != nil {
71-
return nil, err
72-
}
73-
74-
if p.Cursor != nil && p.Cursor.Last != nil {
75-
reverse(items)
76-
startCursor, endCursor = endCursor, startCursor
77-
}
78-
79-
for _, item := range items {
80-
if err := consumer.Consume(item); err != nil {
81-
return nil, err
82-
}
83-
}
84-
85-
hasNextPage, hasPreviousPage := pageInfo(p, hasMore)
86-
87-
return usecasex.NewPageInfo(count, startCursor, endCursor, hasNextPage, hasPreviousPage), nil
30+
return c.paginate(ctx, rawFilter, s, p, filter, consumer, opts)
8831
}
8932

9033
func (c *Collection) PaginateAggregation(ctx context.Context, pipeline []any, s *usecasex.Sort, p *usecasex.Pagination, consumer Consumer, opts ...*options.AggregateOptions) (*usecasex.PageInfo, error) {
@@ -327,3 +270,84 @@ func sortDirection(p usecasex.Pagination, s *usecasex.Sort) int {
327270
}
328271
return 1
329272
}
273+
274+
func (c *Collection) PaginateProject(ctx context.Context, rawFilter any, s *usecasex.Sort, p *usecasex.Pagination, consumer Consumer, opts ...*options.FindOptions) (*usecasex.PageInfo, error) {
275+
if p == nil || (p.Cursor == nil && p.Offset == nil) {
276+
return nil, nil
277+
}
278+
279+
pFilter, err := c.pageFilter(ctx, *p, s)
280+
if err != nil {
281+
return nil, rerror.ErrInternalByWithContext(ctx, err)
282+
}
283+
284+
filter := rawFilter
285+
if pFilter != nil {
286+
filter = AddCondition(rawFilter, "", pFilter)
287+
}
288+
289+
return c.paginate(ctx, rawFilter, s, p, filter, consumer, opts)
290+
291+
}
292+
293+
func (c *Collection) paginate(ctx context.Context, rawFilter any, s *usecasex.Sort, p *usecasex.Pagination, filter any, consumer Consumer, opts []*options.FindOptions) (*usecasex.PageInfo, error) {
294+
295+
sortKey := idKey
296+
sortOrder := 1
297+
if s != nil && s.Key != "" {
298+
sortKey = s.Key
299+
if s.Reverted {
300+
sortOrder = -1
301+
}
302+
}
303+
304+
if p.Cursor != nil && p.Cursor.Last != nil {
305+
sortOrder *= -1
306+
}
307+
308+
sort := bson.D{{Key: sortKey, Value: sortOrder}}
309+
if sortKey != idKey {
310+
sort = append(sort, bson.E{Key: idKey, Value: sortOrder})
311+
}
312+
313+
findOpts := options.Find().
314+
SetSort(sort).
315+
SetLimit(limit(*p))
316+
317+
if p.Offset != nil {
318+
findOpts.SetSkip(p.Offset.Offset)
319+
}
320+
321+
cursor, err := c.collection.Find(ctx, filter, append([]*options.FindOptions{findOpts}, opts...)...)
322+
if err != nil {
323+
return nil, rerror.ErrInternalByWithContext(ctx, fmt.Errorf("failed to find: %w", err))
324+
}
325+
defer func() {
326+
_ = cursor.Close(ctx)
327+
}()
328+
329+
count, err := c.collection.CountDocuments(ctx, rawFilter)
330+
if err != nil {
331+
return nil, rerror.ErrInternalByWithContext(ctx, fmt.Errorf("failed to count: %w", err))
332+
}
333+
334+
items, startCursor, endCursor, hasMore, err := consume(ctx, cursor, limit(*p))
335+
if err != nil {
336+
return nil, err
337+
}
338+
339+
if p.Cursor != nil && p.Cursor.Last != nil {
340+
reverse(items)
341+
startCursor, endCursor = endCursor, startCursor
342+
}
343+
344+
for _, item := range items {
345+
if err := consumer.Consume(item); err != nil {
346+
return nil, err
347+
}
348+
}
349+
350+
hasNextPage, hasPreviousPage := pageInfo(p, hasMore)
351+
352+
return usecasex.NewPageInfo(count, startCursor, endCursor, hasNextPage, hasPreviousPage), nil
353+
}

mongox/util.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,58 @@ func And(filter interface{}, key string, f interface{}) interface{} {
157157
}
158158
return AppendE(filter, bson.E{Key: key, Value: f})
159159
}
160+
161+
func isEmptyCondition(condition interface{}) bool {
162+
switch c := condition.(type) {
163+
case bson.M:
164+
return len(c) == 0
165+
case bson.D:
166+
return len(c) == 0
167+
case bson.A:
168+
return len(c) == 0
169+
case []bson.M:
170+
return len(c) == 0
171+
case []bson.D:
172+
return len(c) == 0
173+
case []bson.A:
174+
return len(c) == 0
175+
case []interface{}:
176+
return len(c) == 0
177+
default:
178+
return false
179+
}
180+
}
181+
182+
func AddCondition(filter interface{}, key string, condition interface{}) interface{} {
183+
if condition == nil || isEmptyCondition(condition) {
184+
return filter
185+
}
186+
187+
filterMap, ok := filter.(bson.M)
188+
if !ok || len(filterMap) == 0 {
189+
filterMap = bson.M{}
190+
}
191+
192+
var newCondition interface{}
193+
if key != "" {
194+
if _, exists := filterMap[key]; exists {
195+
return filter
196+
}
197+
newCondition = bson.M{key: condition}
198+
} else {
199+
newCondition = condition
200+
}
201+
202+
if existingAnd, ok := filterMap["$and"].(bson.A); ok {
203+
filterMap["$and"] = append(existingAnd, newCondition)
204+
} else {
205+
existingConditions := make(bson.A, 0)
206+
for k, v := range filterMap {
207+
if k != "$and" {
208+
existingConditions = append(existingConditions, bson.M{k: v})
209+
}
210+
}
211+
filterMap["$and"] = append(existingConditions, newCondition)
212+
}
213+
return filterMap
214+
}

0 commit comments

Comments
 (0)