Skip to content

Commit 1eb0f8c

Browse files
authored
Merge pull request #23 from jiangz222/aggregate
support aggregate
2 parents 0bfc06b + 985395d commit 1eb0f8c

17 files changed

+385
-170
lines changed

README.md

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ var oneUserInfo = UserInfo{
8686
Create index
8787

8888
```go
89-
cli.EnsureIndexes(ctx, []string{"name"}, []string{"age", "name,weight"})
89+
cli.EnsureIndexes(ctx, []string{}, []string{"age", "name,weight"})
9090
```
9191

9292
- Insert a document
@@ -113,36 +113,41 @@ err = cli.Remove(ctx, BsonT{"age": 7})
113113
- Insert multiple data
114114

115115
```go
116-
// batch insert
116+
// multiple insert
117117
var batchUserInfoI = []interface{}{
118-
UserInfo{Name: "wxy", Age: 6, Weight: 20},
119-
UserInfo{Name: "jZ", Age: 6, Weight: 25},
120-
UserInfo{Name: "zp", Age: 6, Weight: 30},
121-
UserInfo{Name: "yxw", Age: 6, Weight: 35},
118+
UserInfo{Name: "a1", Age: 6, Weight: 20},
119+
UserInfo{Name: "b2", Age: 6, Weight: 25},
120+
UserInfo{Name: "c3", Age: 6, Weight: 30},
121+
UserInfo{Name: "d4", Age: 6, Weight: 35},
122+
UserInfo{Name: "a1", Age: 7, Weight: 40},
123+
UserInfo{Name: "a1", Age: 8, Weight: 45},
122124
}
123125
result, err = cli.Collection.InsertMany(ctx, batchUserInfoI)
124126
```
125127

126128
- Search all, sort and limit
127-
128129
```go
129130
// find all, sort and limit
130131
batch := []UserInfo{}
131132
cli.Find(ctx, BsonT{"age": 6}).Sort("weight").Limit(7).All(&batch)
132133
```
133-
134+
- Count
135+
````go
136+
count, err := cli.Find(ctx, BsonT{"age": 6}).Count()
137+
````
138+
- Aggregate
139+
```go
140+
matchStage := qmgo.D{{"$match", []qmgo.E{{"weight", qmgo.D{{"$gt", 30}}}}}}
141+
groupStage := qmgo.D{{"$group", qmgo.D{{"_id", "$name"}, {"total", qmgo.D{{"$sum", "$age"}}}}}}
142+
var showsWithInfo []qmgo.M
143+
err = cli.Aggregate(context.Background(), qmgo.Pipeline{matchStage, groupStage}).All(&showsWithInfo)
144+
```
134145
## Feature
135-
136-
- Supported
137-
- CRUD to documents
138-
- Create indexes
139-
- Sort、limit、count
140-
- TODO
141-
- Transaction
142-
- Aggregate
143-
- Options for every operation
144-
145-
146+
- CRUD to documents
147+
- Create indexes
148+
- Sort、limit、count、select
149+
- Cursor
150+
- Aggregate
146151

147152
## `qmgo` vs `mgo` vs `go.mongodb.org/mongo-driver`
148153

@@ -155,8 +160,8 @@ How do we do in`go.mongodb.org/mongo-driver`:
155160
// find all, sort and limit
156161
findOptions := options.Find()
157162
findOptions.SetLimit(7) // set limit
158-
var sorts bson.D
159-
sorts = append(sorts, bson.E{Key: "weight", Value: 1})
163+
var sorts D
164+
sorts = append(sorts, E{Key: "weight", Value: 1})
160165
findOptions.SetSort(sorts) // set sort
161166

162167
batch := []UserInfo{}

README_ZH.md

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ var oneUserInfo = UserInfo{
7878
创建索引
7979

8080
```go
81-
cli.EnsureIndexes(ctx, []string{"name"}, []string{"age", "name,weight"})
81+
cli.EnsureIndexes(ctx, []string{}, []string{"age", "name,weight"})
8282
```
8383

8484
- 插入一个文档
@@ -105,12 +105,14 @@ err = cli.Remove(ctx, BsonT{"age": 7})
105105
- 插入多条数据
106106

107107
```go
108-
// batch insert
108+
// multiple insert
109109
var batchUserInfoI = []interface{}{
110-
UserInfo{Name: "wxy", Age: 6, Weight: 20},
111-
UserInfo{Name: "jZ", Age: 6, Weight: 25},
112-
UserInfo{Name: "zp", Age: 6, Weight: 30},
113-
UserInfo{Name: "yxw", Age: 6, Weight: 35},
110+
UserInfo{Name: "a1", Age: 6, Weight: 20},
111+
UserInfo{Name: "b2", Age: 6, Weight: 25},
112+
UserInfo{Name: "c3", Age: 6, Weight: 30},
113+
UserInfo{Name: "d4", Age: 6, Weight: 35},
114+
UserInfo{Name: "a1", Age: 7, Weight: 40},
115+
UserInfo{Name: "a1", Age: 8, Weight: 45},
114116
}
115117
result, err = cli.Collection.InsertMany(ctx, batchUserInfoI)
116118
```
@@ -123,17 +125,26 @@ batch := []UserInfo{}
123125
cli.Find(ctx, BsonT{"age": 6}).Sort("weight").Limit(7).All(&batch)
124126
```
125127

126-
## 功能
128+
- Count
129+
````go
130+
count, err := cli.Find(ctx, BsonT{"age": 6}).Count()
131+
````
127132

128-
- 已经支持
129-
- 文档的增删改查
130-
- 索引配置
131-
- 查询`Sort``Limit``Count`
133+
- Aggregate
134+
```go
135+
matchStage := qmgo.D{{"$match", []qmgo.E{{"weight", qmgo.D{{"$gt", 30}}}}}}
136+
groupStage := qmgo.D{{"$group", qmgo.D{{"_id", "$name"}, {"total", qmgo.D{{"$sum", "$age"}}}}}}
137+
var showsWithInfo []qmgo.M
138+
err = cli.Aggregate(context.Background(), qmgo.Pipeline{matchStage, groupStage}).All(&showsWithInfo)
139+
```
140+
141+
## 功能
142+
- 文档的增删改查
143+
- 索引配置
144+
- `Sort``Limit``Count``Select`
145+
- `Cursor`
146+
- 聚合`Aggregate`
132147

133-
- TODO:
134-
- 事务
135-
- 聚合`Aggregate`
136-
- 操作支持`Options`
137148

138149
## `qmgo` vs `mgo` vs `go.mongodb.org/mongo-driver`
139150

@@ -146,8 +157,8 @@ cli.Find(ctx, BsonT{"age": 6}).Sort("weight").Limit(7).All(&batch)
146157
// find all 、sort and limit
147158
findOptions := options.Find()
148159
findOptions.SetLimit(7) // set limit
149-
var sorts bson.D
150-
sorts = append(sorts, bson.E{Key: "weight", Value: 1})
160+
var sorts D
161+
sorts = append(sorts, E{Key: "weight", Value: 1})
151162
findOptions.SetSort(sorts) // set sort
152163

153164
batch := []UserInfo{}

aggregate.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package qmgo
2+
3+
import (
4+
"context"
5+
6+
"go.mongodb.org/mongo-driver/bson"
7+
"go.mongodb.org/mongo-driver/mongo"
8+
)
9+
10+
type Pipeline []bson.D
11+
12+
type Aggregate struct {
13+
ctx context.Context
14+
pipeline interface{}
15+
collection *mongo.Collection
16+
}
17+
18+
// All iterates the cursor from aggregate and decodes each document into results.
19+
func (a *Aggregate) All(results interface{}) error {
20+
c, err := a.collection.Aggregate(a.ctx, a.pipeline)
21+
if err != nil {
22+
return err
23+
}
24+
return c.All(a.ctx, results)
25+
}
26+
27+
// One iterates the cursor from aggregate and decodes current document into result.
28+
func (a *Aggregate) One(result interface{}) error {
29+
c, err := a.collection.Aggregate(a.ctx, a.pipeline)
30+
if err != nil {
31+
return err
32+
}
33+
cr := Cursor{
34+
ctx: a.ctx,
35+
cursor: c,
36+
err: err,
37+
}
38+
defer cr.Close()
39+
if !cr.Next(result) {
40+
return ERR_NO_SUCH_RECORD
41+
}
42+
return err
43+
}
44+
45+
// Iter return the cursor after aggregate
46+
func (a *Aggregate) Iter() CursorI {
47+
c, err := a.collection.Aggregate(a.ctx, a.pipeline)
48+
return &Cursor{
49+
ctx: a.ctx,
50+
cursor: c,
51+
err: err,
52+
}
53+
}

aggregate_test.go

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package qmgo
2+
3+
import (
4+
"context"
5+
"errors"
6+
"testing"
7+
8+
"github.com/stretchr/testify/require"
9+
"go.mongodb.org/mongo-driver/bson"
10+
"go.mongodb.org/mongo-driver/bson/primitive"
11+
)
12+
13+
func TestAggregate(t *testing.T) {
14+
ast := require.New(t)
15+
16+
var cli *QmgoClient
17+
18+
cli = initClient("test")
19+
cli.DropCollection(context.Background())
20+
cli.EnsureIndexes(context.Background(), nil, []string{"name"})
21+
22+
id1 := primitive.NewObjectID()
23+
id2 := primitive.NewObjectID()
24+
id3 := primitive.NewObjectID()
25+
id4 := primitive.NewObjectID()
26+
id5 := primitive.NewObjectID()
27+
docs := []interface{}{
28+
QueryTestItem{Id: id1, Name: "Alice", Age: 10},
29+
QueryTestItem{Id: id2, Name: "Alice", Age: 12},
30+
QueryTestItem{Id: id3, Name: "Lucas", Age: 33},
31+
QueryTestItem{Id: id4, Name: "Lucas", Age: 22},
32+
QueryTestItem{Id: id5, Name: "Lucas", Age: 44},
33+
}
34+
cli.InsertMany(context.Background(), docs)
35+
matchStage := bson.D{{"$match", []bson.E{{"age", bson.D{{"$gt", 11}}}}}}
36+
groupStage := bson.D{{"$group", bson.D{{"_id", "$name"}, {"total", bson.D{{"$sum", "$age"}}}}}}
37+
var showsWithInfo []bson.M
38+
// aggregate ALL()
39+
err := cli.Aggregate(context.Background(), Pipeline{matchStage, groupStage}).All(&showsWithInfo)
40+
ast.NoError(err)
41+
ast.Equal(2, len(showsWithInfo))
42+
for _, v := range showsWithInfo {
43+
if "Alice" == v["_id"] {
44+
ast.Equal(int32(12), v["total"])
45+
continue
46+
}
47+
if "Lucas" == v["_id"] {
48+
ast.Equal(int32(99), v["total"])
49+
continue
50+
}
51+
ast.Error(errors.New("error"), "impossible")
52+
}
53+
// Iter()
54+
iter := cli.Aggregate(context.Background(), Pipeline{matchStage, groupStage})
55+
ast.NotNil(iter)
56+
err = iter.All(&showsWithInfo)
57+
ast.NoError(err)
58+
for _, v := range showsWithInfo {
59+
if "Alice" == v["_id"] {
60+
ast.Equal(int32(12), v["total"])
61+
continue
62+
}
63+
if "Lucas" == v["_id"] {
64+
ast.Equal(int32(99), v["total"])
65+
continue
66+
}
67+
ast.Error(errors.New("error"), "impossible")
68+
}
69+
// One()
70+
var oneInfo bson.M
71+
72+
iter = cli.Aggregate(context.Background(), Pipeline{matchStage, groupStage})
73+
ast.NotNil(iter)
74+
75+
err = iter.One(&oneInfo)
76+
ast.NoError(err)
77+
ast.Equal(true, oneInfo["_id"] == "Alice" || oneInfo["_id"] == "Lucas")
78+
79+
// iter
80+
iter = cli.Aggregate(context.Background(), Pipeline{matchStage, groupStage})
81+
ast.NotNil(iter)
82+
83+
i := iter.Iter()
84+
85+
ct := i.Next(&oneInfo)
86+
ast.Equal(true, oneInfo["_id"] == "Alice" || oneInfo["_id"] == "Lucas")
87+
ast.Equal(true, ct)
88+
ct = i.Next(&oneInfo)
89+
ast.Equal(true, oneInfo["_id"] == "Alice" || oneInfo["_id"] == "Lucas")
90+
ast.Equal(true, ct)
91+
ct = i.Next(&oneInfo)
92+
ast.Equal(false, ct)
93+
94+
// err
95+
ast.Error(cli.Aggregate(context.Background(), 1).All(&showsWithInfo))
96+
ast.Error(cli.Aggregate(context.Background(), 1).One(&showsWithInfo))
97+
ast.Error(cli.Aggregate(context.Background(), 1).Iter().Err())
98+
matchStage = bson.D{{"$match", []bson.E{{"age", bson.D{{"$gt", 100}}}}}}
99+
groupStage = bson.D{{"$group", bson.D{{"_id", "$name"}, {"total", bson.D{{"$sum", "$age"}}}}}}
100+
ast.Error(cli.Aggregate(context.Background(), Pipeline{matchStage, groupStage}).One(&showsWithInfo))
101+
102+
}

base.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package qmgo
22

33
import (
44
"strings"
5-
"time"
65
)
76

87
// QmgoConfig for initial mongodb instance
@@ -31,10 +30,10 @@ func IsDup(err error) bool {
3130
return strings.Contains(err.Error(), "E11000")
3231
}
3332

34-
// Now return Millisecond current time
35-
func Now() time.Time {
36-
return time.Unix(0, time.Now().UnixNano()/1e6*1e6)
37-
}
33+
//// Now return Millisecond current time
34+
//func Now() time.Time {
35+
// return time.Unix(0, time.Now().UnixNano()/1e6*1e6)
36+
//}
3837

3938
// SplitSortField handle sort symbol: "+"/"-" in front of field
4039
// if "+", return sort as 1

client.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ func Open(ctx context.Context, conf *Config) (cli *QmgoClient, err error) {
2727
}
2828

2929
db := client.Database(conf.Database)
30-
if err != nil {
31-
fmt.Println("new database fail", err)
32-
return
33-
}
34-
3530
coll := db.Collection(conf.Coll)
3631

3732
cli = &QmgoClient{

0 commit comments

Comments
 (0)