forked from getporter/cnab-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mongodb.go
148 lines (125 loc) · 3.13 KB
/
mongodb.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
package crud
import (
"fmt"
"net/url"
"strings"
"github.com/globalsign/mgo"
)
// MongoCollectionPrefix is applied to every collection.
const MongoCollectionPrefix = "cnab_"
var _ Store = &mongoDBStore{}
type mongoDBStore struct {
url string
session *mgo.Session
collections map[string]*mgo.Collection
dbName string
}
type doc struct {
Name string `json:"name"`
Group string `json:"group"`
Data []byte `json:"data"`
}
// NewMongoDBStore creates a new storage engine that uses MongoDB
//
// The URL provided must point to a MongoDB server and database.
func NewMongoDBStore(url string) Store {
db := &mongoDBStore{
url: url,
collections: map[string]*mgo.Collection{},
}
return NewBackingStore(db)
}
func (s *mongoDBStore) Connect() error {
dbn, err := parseDBName(s.url)
if err != nil {
return err
}
s.dbName = dbn
session, err := mgo.Dial(s.url)
if err != nil {
return err
}
s.session = session
return nil
}
func (s *mongoDBStore) Close() error {
if s.session != nil {
s.session.Close()
s.session = nil
}
return nil
}
func (s *mongoDBStore) getCollection(itemType string) *mgo.Collection {
c := s.collections[itemType]
if c == nil {
c = s.session.DB(s.dbName).C(MongoCollectionPrefix + itemType)
s.collections[itemType] = c
}
return c
}
func (s *mongoDBStore) Count(itemType string, group string) (int, error) {
collection := s.getCollection(itemType)
var query map[string]string
if group != "" {
query = map[string]string{
"group": group,
}
}
n, err := collection.Find(query).Count()
return n, wrapErr(err)
}
func (s *mongoDBStore) List(itemType string, group string) ([]string, error) {
collection := s.getCollection(itemType)
var res []doc
var query map[string]string
if group != "" {
query = map[string]string{
"group": group,
}
}
if err := collection.Find(query).All(&res); err != nil {
return []string{}, wrapErr(err)
}
buf := []string{}
for _, v := range res {
buf = append(buf, v.Name)
}
return buf, nil
}
func (s *mongoDBStore) Save(itemType string, group string, name string, data []byte) error {
collection := s.getCollection(itemType)
return wrapErr(collection.Insert(doc{Name: name, Group: group, Data: data}))
}
func (s *mongoDBStore) Read(itemType string, name string) ([]byte, error) {
collection := s.getCollection(itemType)
res := doc{}
if err := collection.Find(map[string]string{"name": name}).One(&res); err != nil {
if err == mgo.ErrNotFound {
return nil, ErrRecordDoesNotExist
}
return []byte{}, wrapErr(err)
}
return res.Data, nil
}
func (s *mongoDBStore) Delete(itemType string, name string) error {
collection := s.getCollection(itemType)
return wrapErr(collection.Remove(map[string]string{"name": name}))
}
func wrapErr(err error) error {
if err == nil {
return err
}
return fmt.Errorf("mongo storage error: %s", err)
}
func parseDBName(dialStr string) (string, error) {
u, err := url.Parse(dialStr)
if err != nil {
return "", err
}
if u.Path != "" {
return strings.TrimPrefix(u.Path, "/"), nil
}
// If this returns empty, then the driver is supposed to substitute in the
// default database.
return "", nil
}