|
|
|
|
package db
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"net/url"
|
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"gopkg.in/mgo.v2"
|
|
|
|
|
"gopkg.in/mgo.v2/bson"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type Config struct {
|
|
|
|
|
Hosts []string
|
|
|
|
|
// AuthSource Specify the database name associated with the user’s credentials.
|
|
|
|
|
// authSource defaults to the database specified in the connection string.
|
|
|
|
|
AuthSource string
|
|
|
|
|
UserName string
|
|
|
|
|
Password string
|
|
|
|
|
Database string
|
|
|
|
|
Timeout time.Duration // second
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Mdb struct {
|
|
|
|
|
*Config
|
|
|
|
|
*mgo.Session
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func NewMdb(c *Config) (*Mdb, error) {
|
|
|
|
|
m := &Mdb{
|
|
|
|
|
Config: c,
|
|
|
|
|
}
|
|
|
|
|
return m, m.connect()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *Mdb) connect() error {
|
|
|
|
|
// connectionString: [mongodb://][user:pass@]host1[:port1][,host2[:port2],...][/database][?options]
|
|
|
|
|
// via: https://docs.mongodb.com/manual/reference/connection-string/
|
|
|
|
|
connectionString := strings.Join(m.Config.Hosts, ",")
|
|
|
|
|
if len(m.Config.UserName) > 0 && len(m.Config.Password) > 0 {
|
|
|
|
|
connectionString = m.Config.UserName + ":" + url.QueryEscape(m.Config.Password) + "@" + connectionString
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(m.Config.Database) > 0 {
|
|
|
|
|
connectionString += "/" + m.Config.Database
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(m.Config.AuthSource) > 0 {
|
|
|
|
|
connectionString += "?authSource=" + m.Config.AuthSource
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
session, err := mgo.DialWithTimeout(connectionString, m.Config.Timeout)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m.Session = session
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *Mdb) WithC(collection string, job func(*mgo.Collection) error) error {
|
|
|
|
|
s := m.Session.New()
|
|
|
|
|
err := job(s.DB(m.Config.Database).C(collection))
|
|
|
|
|
s.Close()
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (self *Mdb) Upsert(collection string, selector interface{}, change interface{}) error {
|
|
|
|
|
return self.WithC(collection, func(c *mgo.Collection) error {
|
|
|
|
|
_, err := c.Upsert(selector, change)
|
|
|
|
|
return err
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (self *Mdb) Insert(collection string, data ...interface{}) error {
|
|
|
|
|
return self.WithC(collection, func(c *mgo.Collection) error {
|
|
|
|
|
return c.Insert(data...)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (self *Mdb) FindId(collection string, id interface{}, result interface{}) error {
|
|
|
|
|
return self.WithC(collection, func(c *mgo.Collection) error {
|
|
|
|
|
return c.Find(bson.M{"_id": id}).One(result)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (self *Mdb) FindOne(collection string, query interface{}, result interface{}) error {
|
|
|
|
|
return self.WithC(collection, func(c *mgo.Collection) error {
|
|
|
|
|
return c.Find(query).One(result)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (self *Mdb) RemoveId(collection string, id interface{}) error {
|
|
|
|
|
return self.WithC(collection, func(c *mgo.Collection) error {
|
|
|
|
|
return c.RemoveId(id)
|
|
|
|
|
})
|
|
|
|
|
}
|