-
Notifications
You must be signed in to change notification settings - Fork 2
/
driver.go
125 lines (114 loc) · 3.41 KB
/
driver.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
package internal
import (
"context"
"errors"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"github.com/gstones/moke-kit/orm/nosql/noptions"
"github.com/gstones/moke-kit/orm/nerrors"
"github.com/gstones/moke-kit/orm/nosql/key"
)
type DatabaseDriver struct {
database *mongo.Database
}
func (dd *DatabaseDriver) GetName() string {
return dd.database.Name()
}
func (dd *DatabaseDriver) Set(key key.Key, opts ...noptions.Option) (noptions.Version, error) {
coll := dd.database.Collection(key.Prefix())
if o, err := noptions.NewOptions(opts...); err != nil {
return noptions.NoVersion, err
} else if o.Source == nil {
return noptions.NoVersion, nerrors.ErrSourceIsNil
} else {
opt := options.Update()
filter := bson.M{"_id": key.String()}
if o.Version != noptions.NoVersion {
filter["version"] = o.Version
} else {
opt.SetUpsert(true)
}
update := bson.M{"$set": bson.M{"data": o.Source}, "$inc": bson.M{"version": 1}}
if res, err := coll.UpdateOne(context.Background(), filter, update, opt); err != nil {
return 0, err
} else {
if res.MatchedCount == 0 && o.Version != noptions.NoVersion {
return 0, nerrors.ErrVersionNotMatch
} else {
return o.Version + 1, nil
}
}
}
}
func (dd *DatabaseDriver) Get(key key.Key, opts ...noptions.Option) (noptions.Version, error) {
coll := dd.database.Collection(key.Prefix())
if o, err := noptions.NewOptions(opts...); err != nil {
return noptions.NoVersion, err
} else {
filter := bson.M{"_id": key.String()}
if o.Version != noptions.NoVersion {
filter["version"] = o.Version
}
if res := coll.FindOne(context.Background(), filter); res.Err() != nil {
if errors.Is(res.Err(), mongo.ErrNoDocuments) {
return 0, nerrors.ErrNotFound
}
return 0, res.Err()
} else {
bRaw := &bson.Raw{}
if err := res.Decode(bRaw); err != nil {
return 0, err
} else {
if err := bRaw.Lookup("data").Unmarshal(o.Destination); err != nil {
return 0, err
}
if err := bRaw.Lookup("version").Unmarshal(&o.Version); err != nil {
return 0, err
}
return o.Version, nil
}
}
}
}
// Delete delete a document by a key
func (dd *DatabaseDriver) Delete(key key.Key) error {
coll := dd.database.Collection(key.Prefix())
filter := bson.M{"_id": key.String()}
if _, err := coll.DeleteOne(context.Background(), filter); err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nerrors.ErrNotFound
}
return err
}
return nil
}
// Incr increments a document from the nosql store. (tips: can not be used for document,because the version)
func (dd *DatabaseDriver) Incr(key key.Key, field string, amount int32) (int64, error) {
coll := dd.database.Collection(key.Prefix())
filter := bson.M{"_id": key.String()}
update := bson.M{"$inc": bson.M{field: amount}}
opt := options.FindOneAndUpdate()
opt.SetUpsert(true)
res := coll.FindOneAndUpdate(context.Background(), filter, update, opt)
if res.Err() != nil {
if errors.Is(res.Err(), mongo.ErrNoDocuments) {
return 0, nerrors.ErrNotFound
}
return 0, res.Err()
}
bRaw := &bson.Raw{}
if err := res.Decode(bRaw); err != nil {
return 0, err
}
var value int64
if err := bRaw.Lookup(field).Unmarshal(&value); err != nil {
return 0, err
}
return value, nil
}
func NewCollectionDriver(database *mongo.Database) (*DatabaseDriver, error) {
return &DatabaseDriver{
database: database,
}, nil
}