-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdb.go
executable file
·187 lines (165 loc) · 3.94 KB
/
db.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// Package mogo provides a faster usage of mongo with mgo behind
package mogo
import (
"errors"
"github.com/fatih/structs"
"github.com/globalsign/mgo"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
var (
// ErrorURI raise for parsing uri error
ErrorURI = errors.New("mogo: could not parse URI")
// ErrorModelID passing a model for update
// if could not find Id or ID with bson.ObjectID will raise
ErrorModelID = errors.New("mogo: model id type error")
)
// DB main connection struct
type DB struct {
Session *mgo.Session
Database *mgo.Database
}
// Conn init db struct with uri -> host:port/db
func Conn(info *mgo.DialInfo) (*DB, error) {
session, err := mgo.DialWithInfo(info)
if err != nil {
return nil, err
}
database := new(DB)
database.Database = session.DB(info.Database)
session.SetSafe(&mgo.Safe{})
session.SetMode(mgo.Monotonic, true)
database.Session = session
return database, nil
}
func ConnByURI(url string) (*DB, error) {
session, err := mgo.Dial(url)
if err != nil {
return nil, err
}
database := new(DB)
database.Database = session.DB(info.Database)
session.SetSafe(&mgo.Safe{})
session.SetMode(mgo.Monotonic, true)
database.Session = session
return database, nil
}
// Close db session
func (db *DB) Close() {
db.Session.Close()
}
// Collection return mgo collection from model
func (db *DB) Collection(model interface{}) *mgo.Collection {
return db.Database.C(colName(model))
}
func (db *DB) Stream(model, query interface{}) *mgo.Iter {
return db.Collection(model).Find(query).Iter()
}
// LoadIndexes reinitialize models indexes
func (db *DB) LoadIndexes(models ...interface{}) {
for _, model := range models {
col := db.Collection(model)
indexes := loadIndex(model)
for i := range indexes {
col.EnsureIndex(indexes[i])
}
}
}
// DropCollection drop a collection
func (db *DB) DropCollection(model interface{}) error {
col := db.Collection(model)
return col.DropCollection()
}
// func (db *DB) SetIndex(model interface{}, index mgo.Index) error {
// col := db.Collection(model)
// return col.EnsureIndex(index)
// }
// Find start generating query
func (db *DB) Find(q bson.M) *Query {
d := new(DB)
d.Session = db.Session.Clone()
d.Database = db.Database
query := new(Query)
query.db = d
query.q = append(query.q, q)
// fmt.Println(query)
return query
}
// Get a model with id
func (db *DB) FindByID(model, id interface{}) error {
if val, ok := id.(string); ok {
id = bson.ObjectIdHex(val)
}
col := db.Collection(model)
return col.FindId(id).One(model)
}
// Create a document in DB
func (db *DB) Create(model interface{}) error {
col := db.Collection(model)
setID(model)
return col.Insert(model)
}
// Update a Document
func (db *DB) Update(model interface{}) error {
col := db.Collection(model)
id, err := getID(model)
if err != nil {
return err
}
query := bson.M{"_id": id}
fieldsUpdate, err := parseBson(model)
if err != nil {
return err
}
if err := col.Update(query, bson.M{"$set": fieldsUpdate}); err != nil {
return err
}
return db.FindByID(model, id)
}
// --------------------- in package ---------------
func parseBson(model interface{}) (bson.M, error) {
b, err := bson.Marshal(model)
if err != nil {
return bson.M{}, err
}
var body bson.M
bson.Unmarshal(b, &body)
return body, nil
}
func setID(model interface{}) {
m := structs.Map(model)
var keyID string
if _, ok := m["Id"]; ok {
m["Id"] = bson.NewObjectId()
keyID = "Id"
}
if _, ok := m["ID"]; ok {
m["ID"] = bson.NewObjectId()
keyID = "ID"
}
s := structs.New(model)
field := s.Field(keyID)
field.Set(m[keyID])
}
func getID(model interface{}) (bson.ObjectId, error) {
m := structs.Map(model)
var (
idInterface interface{}
id bson.ObjectId
ok bool
)
if val, ok := m["Id"]; ok {
idInterface = val
}
if val, ok := m["ID"]; ok {
idInterface = val
}
id, ok = idInterface.(bson.ObjectId)
if !ok {
return id, ErrorModelID
}
if !id.Valid() {
return id, ErrorModelID
}
return id, nil
}