forked from Kamva/mgm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
collection.go
165 lines (136 loc) · 6.89 KB
/
collection.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package mgm
import (
"context"
"github.com/kamva/mgm/v3/builder"
"github.com/kamva/mgm/v3/field"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
// Collection performs operations on models and the given Mongodb collection
type Collection struct {
*mongo.Collection
}
// FindByID method finds a doc and decodes it to a model, otherwise returns an error.
// The id field can be any value that if passed to the `PrepareID` method, it returns
// a valid ID (e.g string, bson.ObjectId).
func (coll *Collection) FindByID(id interface{}, model Model, opts ...*options.FindOneOptions) error {
return coll.FindByIDWithCtx(ctx(), id, model, opts...)
}
// FindByIDWithCtx method finds a doc and decodes it to a model, otherwise returns an error.
// The id field can be any value that if passed to the `PrepareID` method, it returns
// a valid ID (e.g string, bson.ObjectId).
func (coll *Collection) FindByIDWithCtx(ctx context.Context, id interface{}, model Model, opts ...*options.FindOneOptions) error {
id, err := model.PrepareID(id)
if err != nil {
return err
}
return first(ctx, coll, bson.M{field.ID: id}, model, opts...)
}
// First method searches and returns the first document in the search results.
func (coll *Collection) First(filter interface{}, model Model, opts ...*options.FindOneOptions) error {
return coll.FirstWithCtx(ctx(), filter, model, opts...)
}
// FirstWithCtx method searches and returns the first document in the search results.
func (coll *Collection) FirstWithCtx(ctx context.Context, filter interface{}, model Model, opts ...*options.FindOneOptions) error {
return first(ctx, coll, filter, model, opts...)
}
// Create method inserts a new model into the database.
func (coll *Collection) Create(model Model, opts ...*options.InsertOneOptions) error {
return coll.CreateWithCtx(ctx(), model, opts...)
}
// CreateWithCtx method inserts a new model into the database.
func (coll *Collection) CreateWithCtx(ctx context.Context, model Model, opts ...*options.InsertOneOptions) error {
return create(ctx, coll, model, opts...)
}
// Update function persists the changes made to a model to the database.
// Calling this method also invokes the model's mgm updating, updated,
// saving, and saved hooks.
func (coll *Collection) Update(model Model, opts ...*options.UpdateOptions) error {
return coll.UpdateWithCtx(ctx(), model, opts...)
}
// UpdateWithCtx function persists the changes made to a model to the database using the specified context.
// Calling this method also invokes the model's mgm updating, updated,
// saving, and saved hooks.
func (coll *Collection) UpdateWithCtx(ctx context.Context, model Model, opts ...*options.UpdateOptions) error {
return update(ctx, coll, model, opts...)
}
// Delete method deletes a model (doc) from a collection.
// To perform additional operations when deleting a model
// you should use hooks rather than overriding this method.
func (coll *Collection) Delete(model Model) error {
return del(ctx(), coll, model)
}
// DeleteWithCtx method deletes a model (doc) from a collection using the specified context.
// To perform additional operations when deleting a model
// you should use hooks rather than overriding this method.
func (coll *Collection) DeleteWithCtx(ctx context.Context, model Model) error {
return del(ctx, coll, model)
}
// SimpleFind finds, decodes and returns the results.
func (coll *Collection) SimpleFind(results interface{}, filter interface{}, opts ...*options.FindOptions) error {
return coll.SimpleFindWithCtx(ctx(), results, filter, opts...)
}
// SimpleFindWithCtx finds, decodes and returns the results using the specified context.
func (coll *Collection) SimpleFindWithCtx(ctx context.Context, results interface{}, filter interface{}, opts ...*options.FindOptions) error {
cur, err := coll.Find(ctx, filter, opts...)
if err != nil {
return err
}
return cur.All(ctx, results)
}
// --------------------------------
// Aggregation methods
// --------------------------------
// SimpleAggregateFirst is just same as SimpleAggregateFirstWithCtx, but doesn't get context param.
func (coll *Collection) SimpleAggregateFirst(result interface{}, stages []interface{}, opts ...*options.AggregateOptions) (bool, error) {
return coll.SimpleAggregateFirstWithCtx(ctx(), result, stages, opts...)
}
// SimpleAggregateFirstWithCtx performs a simple aggregation, decodes the first aggregate result and returns it using the provided result parameter.
// The value of `stages` can be Operator|bson.M
// Note: you can not use this method in a transaction because it does not accept a context.
// To participate in transactions, please use the regular aggregation method.
func (coll *Collection) SimpleAggregateFirstWithCtx(ctx context.Context, result interface{}, stages []interface{}, opts ...*options.AggregateOptions) (bool, error) {
cur, err := coll.SimpleAggregateCursorWithCtx(ctx, stages, opts...)
if err != nil {
return false, err
}
if cur.Next(ctx) {
return true, cur.Decode(result)
}
return false, nil
}
// SimpleAggregate is just same as SimpleAggregateWithCtx, but doesn't get context param.
func (coll *Collection) SimpleAggregate(results interface{}, stages []interface{}, opts ...*options.AggregateOptions) error {
return coll.SimpleAggregateWithCtx(ctx(), results, stages, opts...)
}
// SimpleAggregateWithCtx performs a simple aggregation, decodes the aggregate result and returns the list using the provided result parameter.
// The value of `stages` can be Operator|bson.M
// Note: you can not use this method in a transaction because it does not accept a context.
// To participate in transactions, please use the regular aggregation method.
func (coll *Collection) SimpleAggregateWithCtx(ctx context.Context, results interface{}, stages []interface{}, opts ...*options.AggregateOptions) error {
cur, err := coll.SimpleAggregateCursorWithCtx(ctx, stages, opts...)
if err != nil {
return err
}
return cur.All(ctx, results)
}
// SimpleAggregateCursor is just same as SimpleAggregateCursorWithCtx, but
// doesn't get context.
func (coll *Collection) SimpleAggregateCursor(stages []interface{}, opts ...*options.AggregateOptions) (*mongo.Cursor, error) {
return coll.SimpleAggregateCursorWithCtx(ctx(), stages, opts...)
}
// SimpleAggregateCursorWithCtx performs a simple aggregation and returns a cursor over the resulting documents.
// Note: you can not use this method in a transaction because it does not accept a context.
// To participate in transactions, please use the regular aggregation method.
func (coll *Collection) SimpleAggregateCursorWithCtx(ctx context.Context, stages []interface{}, opts ...*options.AggregateOptions) (*mongo.Cursor, error) {
pipeline := bson.A{}
for _, stage := range stages {
if operator, ok := stage.(builder.Operator); ok {
pipeline = append(pipeline, builder.S(operator))
} else {
pipeline = append(pipeline, stage)
}
}
return coll.Aggregate(ctx, pipeline, opts...)
}