2022-02-09 21:57:31 +01:00
|
|
|
package mgocrud
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2022-02-10 14:59:39 +01:00
|
|
|
"fmt"
|
|
|
|
"runtime"
|
2022-02-09 21:57:31 +01:00
|
|
|
|
|
|
|
mgo "gopkg.in/mgo.v2"
|
|
|
|
)
|
|
|
|
|
|
|
|
type MgoConnection struct {
|
|
|
|
connection *mgo.Session
|
2022-02-10 14:59:39 +01:00
|
|
|
closed bool
|
2022-02-09 21:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewMgoConnection(dial string) (Connection, error) {
|
2022-02-10 14:59:39 +01:00
|
|
|
fmt.Println("CONNECTION CREATE")
|
2022-02-09 21:57:31 +01:00
|
|
|
connection, err := mgo.Dial(dial)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
connection.SetMode(mgo.Monotonic, true)
|
2022-02-10 14:59:39 +01:00
|
|
|
c := &MgoConnection{connection: connection}
|
|
|
|
runtime.SetFinalizer(c, func(c *MgoConnection) {
|
|
|
|
fmt.Println("CONNECTION CLOSE FINALIZER")
|
|
|
|
if !c.closed {
|
|
|
|
c.Close()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return c, nil
|
2022-02-09 21:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoConnection) Close() {
|
2022-02-10 14:59:39 +01:00
|
|
|
fmt.Println("CONNECTION CLOSE MANUALLY")
|
|
|
|
if !c.closed {
|
|
|
|
c.connection.Close()
|
|
|
|
c.closed = true
|
|
|
|
}
|
|
|
|
runtime.SetFinalizer(c, nil)
|
2022-02-09 21:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type MgoSession struct {
|
|
|
|
session *mgo.Session
|
2022-02-10 14:59:39 +01:00
|
|
|
closed bool
|
2022-02-09 21:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MgoSession) Close() {
|
2022-02-10 14:59:39 +01:00
|
|
|
fmt.Println("SESSION CLOSE MANUALLY")
|
|
|
|
if !s.closed {
|
|
|
|
s.session.Close()
|
|
|
|
s.closed = true
|
|
|
|
}
|
|
|
|
runtime.SetFinalizer(s, nil)
|
2022-02-09 21:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoConnection) NewSession() Session {
|
2022-02-10 14:59:39 +01:00
|
|
|
fmt.Println("SESSION CREATE")
|
|
|
|
s := &MgoSession{session: c.connection.Copy()}
|
|
|
|
runtime.SetFinalizer(s, func(s *MgoSession) {
|
|
|
|
fmt.Println("SESSION CLOSE FINALIZER")
|
|
|
|
if !s.closed {
|
|
|
|
s.Close()
|
|
|
|
}
|
|
|
|
})
|
2022-02-09 21:57:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type MgoDatabase struct {
|
|
|
|
database *mgo.Database
|
|
|
|
session Session
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *MgoSession) DB(name string) Database {
|
|
|
|
return &MgoDatabase{database: s.session.DB(name), session: s}
|
|
|
|
}
|
|
|
|
|
|
|
|
type MgoCollection struct {
|
|
|
|
collection *mgo.Collection
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *MgoDatabase) Session() Session {
|
|
|
|
return db.session
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *MgoDatabase) C(name string) Collection {
|
|
|
|
return &MgoCollection{collection: db.database.C(name)}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (db *MgoDatabase) Name() string {
|
|
|
|
return db.database.Name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) Insert(docs ...interface{}) error {
|
|
|
|
return c.collection.Insert(docs...)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) UpdateId(id interface{}, update interface{}) error {
|
|
|
|
return c.collection.UpdateId(id, update)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) RemoveId(id interface{}) error {
|
|
|
|
return c.collection.RemoveId(id)
|
|
|
|
}
|
|
|
|
|
|
|
|
type MgoChangeInfo struct {
|
|
|
|
changeInfo *mgo.ChangeInfo
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ci *MgoChangeInfo) Matched() int {
|
|
|
|
return ci.changeInfo.Matched
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ci *MgoChangeInfo) Removed() int {
|
|
|
|
return ci.changeInfo.Removed
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ci *MgoChangeInfo) Updated() int {
|
|
|
|
return ci.changeInfo.Updated
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) Upsert(selector interface{}, update interface{}) (ChangeInfo, error) {
|
|
|
|
ci, err := c.collection.Upsert(selector, update)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &MgoChangeInfo{changeInfo: ci}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) RemoveAll(filter interface{}) (ChangeInfo, error) {
|
|
|
|
ci, err := c.collection.RemoveAll(filter)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return &MgoChangeInfo{changeInfo: ci}, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type MgoQuery struct {
|
|
|
|
query *mgo.Query
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) FindId(id interface{}) Query {
|
|
|
|
return &MgoQuery{query: c.collection.FindId(id)}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) Find(query interface{}) Query {
|
|
|
|
return &MgoQuery{query: c.collection.Find(query)}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *MgoQuery) Select(selector interface{}) Query {
|
|
|
|
q.query = q.query.Select(selector)
|
|
|
|
return q
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *MgoQuery) One(result interface{}) error {
|
|
|
|
err := q.query.One(result)
|
|
|
|
if err == mgo.ErrNotFound {
|
|
|
|
err = ErrNotFound
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *MgoQuery) Sort(fields ...string) Query {
|
|
|
|
q.query = q.query.Sort(fields...)
|
|
|
|
return q
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *MgoQuery) Skip(n int) Query {
|
|
|
|
q.query = q.query.Skip(n)
|
|
|
|
return q
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *MgoQuery) Limit(n int) Query {
|
|
|
|
q.query = q.query.Limit(n)
|
|
|
|
return q
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *MgoQuery) All(result interface{}) error {
|
|
|
|
err := q.query.All(result)
|
|
|
|
if err == mgo.ErrNotFound {
|
|
|
|
err = ErrNotFound
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *MgoQuery) Count() (int, error) {
|
|
|
|
c, err := q.query.Count()
|
|
|
|
if err == mgo.ErrNotFound {
|
|
|
|
err = ErrNotFound
|
|
|
|
}
|
|
|
|
return c, err
|
|
|
|
}
|
|
|
|
|
|
|
|
type MgoIndex struct {
|
|
|
|
index *mgo.Index
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewMgoIndex(index mgo.Index) Index {
|
|
|
|
return &MgoIndex{index: &index}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) EnsureIndex(index Index) error {
|
|
|
|
if i, ok := index.(*MgoIndex); ok {
|
|
|
|
if i != nil && i.index != nil {
|
|
|
|
return c.collection.EnsureIndex(*i.index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors.New("index parameter not initialized with mgo.Index")
|
|
|
|
}
|
|
|
|
|
|
|
|
type MgoPipe struct {
|
|
|
|
pipe *mgo.Pipe
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *MgoPipe) All(result interface{}) error {
|
|
|
|
err := p.pipe.All(result)
|
|
|
|
if err == mgo.ErrNotFound {
|
|
|
|
err = ErrNotFound
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MgoCollection) Pipe(pipeline interface{}) Pipe {
|
|
|
|
return &MgoPipe{pipe: c.collection.Pipe(pipeline).AllowDiskUse()}
|
|
|
|
}
|