Skip to content

Commit 116bb88

Browse files
lifeng342lifeng.lif
andauthored
feat(finder): support skip, limit and sort (#77)
Co-authored-by: lifeng.lif <[email protected]>
1 parent f2dc64b commit 116bb88

File tree

4 files changed

+198
-33
lines changed

4 files changed

+198
-33
lines changed

bsonx/bsonx.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,23 @@ func dToM(d bson.D) bson.M {
8989
}
9090
return m
9191
}
92+
93+
// StringSortToBsonD transform string sort to bson D
94+
// "-created_at" => bson.D{{"created_at", -1}}
95+
// []string{"age", "-created_at"} => bson.D{{"age", 1}, {"created_at", -1}}
96+
func StringSortToBsonD(sorts ...string) bson.D {
97+
var res bson.D
98+
for _, sort := range sorts {
99+
if len(sort) == 0 || sort == "-" {
100+
continue
101+
}
102+
103+
if sort[0] == '-' {
104+
res = append(res, bson.E{Key: sort[1:], Value: -1})
105+
} else {
106+
res = append(res, bson.E{Key: sort, Value: 1})
107+
}
108+
}
109+
110+
return res
111+
}

bsonx/bsonx_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,40 @@ func TestA(t *testing.T) {
6262
}
6363

6464
}
65+
66+
func TestStringSortToBsonD(t *testing.T) {
67+
testCases := []struct {
68+
name string
69+
value any
70+
want bson.D
71+
}{
72+
{
73+
name: "empty string",
74+
value: []string{""},
75+
want: nil,
76+
},
77+
{
78+
name: "only minus sign",
79+
value: []string{"-"},
80+
want: nil,
81+
},
82+
{
83+
name: "one sort",
84+
value: []string{"-created_at"},
85+
want: bson.D{{Key: "created_at", Value: -1}},
86+
},
87+
{
88+
name: "two sort",
89+
value: []string{"age", "-created_at"},
90+
want: bson.D{{Key: "age", Value: 1}, {Key: "created_at", Value: -1}},
91+
},
92+
}
93+
94+
for _, tc := range testCases {
95+
t.Run(tc.name, func(t *testing.T) {
96+
w, _ := bson.Marshal(tc.want)
97+
v, _ := bson.Marshal(StringSortToBsonD(tc.value.([]string)...))
98+
assert.Equal(t, string(w), string(v))
99+
})
100+
}
101+
}

finder/finder.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ type Finder[T any] struct {
4545
modelHook any
4646
beforeHooks []beforeHookFn
4747
afterHooks []afterHookFn[T]
48+
49+
skip, limit int64
50+
sort any
4851
}
4952

5053
func (f *Finder[T]) RegisterBeforeHooks(hooks ...beforeHookFn) *Finder[T] {
@@ -66,6 +69,21 @@ func (f *Finder[T]) Filter(filter any) *Finder[T] {
6669
return f
6770
}
6871

72+
func (f *Finder[T]) Limit(limit int64) *Finder[T] {
73+
f.limit = limit
74+
return f
75+
}
76+
77+
func (f *Finder[T]) Skip(skip int64) *Finder[T] {
78+
f.skip = skip
79+
return f
80+
}
81+
82+
func (f *Finder[T]) Sort(sort any) *Finder[T] {
83+
f.sort = sort
84+
return f
85+
}
86+
6987
func (f *Finder[T]) Updates(update any) *Finder[T] {
7088
f.updates = update
7189
return f
@@ -109,6 +127,10 @@ func (f *Finder[T]) postActionHandler(ctx context.Context, globalOpContext *oper
109127
}
110128

111129
func (f *Finder[T]) FindOne(ctx context.Context, opts ...options.Lister[options.FindOneOptions]) (*T, error) {
130+
if f.sort != nil {
131+
opts = append(opts, options.FindOne().SetSort(f.sort))
132+
}
133+
112134
t := new(T)
113135

114136
globalOpContext := operation.NewOpContext(f.collection, operation.WithDoc(t), operation.WithFilter(f.filter), operation.WithMongoOptions(opts), operation.WithModelHook(f.modelHook))
@@ -131,6 +153,16 @@ func (f *Finder[T]) FindOne(ctx context.Context, opts ...options.Lister[options.
131153
}
132154

133155
func (f *Finder[T]) Find(ctx context.Context, opts ...options.Lister[options.FindOptions]) ([]*T, error) {
156+
if f.sort != nil {
157+
opts = append(opts, options.Find().SetSort(f.sort))
158+
}
159+
if f.skip != 0 {
160+
opts = append(opts, options.Find().SetSkip(f.skip))
161+
}
162+
if f.limit != 0 {
163+
opts = append(opts, options.Find().SetLimit(f.limit))
164+
}
165+
134166
t := make([]*T, 0)
135167

136168
opContext := operation.NewOpContext(f.collection, operation.WithFilter(f.filter), operation.WithMongoOptions(opts), operation.WithModelHook(f.modelHook))

0 commit comments

Comments
 (0)