github.com/lingyao2333/mo-zero@v1.4.1/core/stores/mongo/model.go (about)

     1  package mongo
     2  
     3  import (
     4  	"log"
     5  	"time"
     6  
     7  	"github.com/globalsign/mgo"
     8  	"github.com/lingyao2333/mo-zero/core/breaker"
     9  )
    10  
    11  // A Model is a mongo model.
    12  type Model struct {
    13  	session    *concurrentSession
    14  	db         *mgo.Database
    15  	collection string
    16  	brk        breaker.Breaker
    17  	opts       []Option
    18  }
    19  
    20  // MustNewModel returns a Model, exits on errors.
    21  func MustNewModel(url, collection string, opts ...Option) *Model {
    22  	model, err := NewModel(url, collection, opts...)
    23  	if err != nil {
    24  		log.Fatal(err)
    25  	}
    26  
    27  	return model
    28  }
    29  
    30  // NewModel returns a Model.
    31  func NewModel(url, collection string, opts ...Option) (*Model, error) {
    32  	session, err := getConcurrentSession(url)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  
    37  	return &Model{
    38  		session: session,
    39  		// If name is empty, the database name provided in the dialed URL is used instead
    40  		db:         session.DB(""),
    41  		collection: collection,
    42  		brk:        breaker.GetBreaker(url),
    43  		opts:       opts,
    44  	}, nil
    45  }
    46  
    47  // Find finds a record with given query.
    48  func (mm *Model) Find(query interface{}) (Query, error) {
    49  	return mm.query(func(c Collection) Query {
    50  		return c.Find(query)
    51  	})
    52  }
    53  
    54  // FindId finds a record with given id.
    55  func (mm *Model) FindId(id interface{}) (Query, error) {
    56  	return mm.query(func(c Collection) Query {
    57  		return c.FindId(id)
    58  	})
    59  }
    60  
    61  // GetCollection returns a Collection with given session.
    62  func (mm *Model) GetCollection(session *mgo.Session) Collection {
    63  	return newCollection(mm.db.C(mm.collection).With(session), mm.brk)
    64  }
    65  
    66  // Insert inserts docs into mm.
    67  func (mm *Model) Insert(docs ...interface{}) error {
    68  	return mm.execute(func(c Collection) error {
    69  		return c.Insert(docs...)
    70  	})
    71  }
    72  
    73  // Pipe returns a Pipe with given pipeline.
    74  func (mm *Model) Pipe(pipeline interface{}) (Pipe, error) {
    75  	return mm.pipe(func(c Collection) Pipe {
    76  		return c.Pipe(pipeline)
    77  	})
    78  }
    79  
    80  // PutSession returns the given session.
    81  func (mm *Model) PutSession(session *mgo.Session) {
    82  	mm.session.putSession(session)
    83  }
    84  
    85  // Remove removes the records with given selector.
    86  func (mm *Model) Remove(selector interface{}) error {
    87  	return mm.execute(func(c Collection) error {
    88  		return c.Remove(selector)
    89  	})
    90  }
    91  
    92  // RemoveAll removes all with given selector and returns a mgo.ChangeInfo.
    93  func (mm *Model) RemoveAll(selector interface{}) (*mgo.ChangeInfo, error) {
    94  	return mm.change(func(c Collection) (*mgo.ChangeInfo, error) {
    95  		return c.RemoveAll(selector)
    96  	})
    97  }
    98  
    99  // RemoveId removes a record with given id.
   100  func (mm *Model) RemoveId(id interface{}) error {
   101  	return mm.execute(func(c Collection) error {
   102  		return c.RemoveId(id)
   103  	})
   104  }
   105  
   106  // TakeSession gets a session.
   107  func (mm *Model) TakeSession() (*mgo.Session, error) {
   108  	return mm.session.takeSession(mm.opts...)
   109  }
   110  
   111  // Update updates a record with given selector.
   112  func (mm *Model) Update(selector, update interface{}) error {
   113  	return mm.execute(func(c Collection) error {
   114  		return c.Update(selector, update)
   115  	})
   116  }
   117  
   118  // UpdateId updates a record with given id.
   119  func (mm *Model) UpdateId(id, update interface{}) error {
   120  	return mm.execute(func(c Collection) error {
   121  		return c.UpdateId(id, update)
   122  	})
   123  }
   124  
   125  // Upsert upserts a record with given selector, and returns a mgo.ChangeInfo.
   126  func (mm *Model) Upsert(selector, update interface{}) (*mgo.ChangeInfo, error) {
   127  	return mm.change(func(c Collection) (*mgo.ChangeInfo, error) {
   128  		return c.Upsert(selector, update)
   129  	})
   130  }
   131  
   132  func (mm *Model) change(fn func(c Collection) (*mgo.ChangeInfo, error)) (*mgo.ChangeInfo, error) {
   133  	session, err := mm.TakeSession()
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	defer mm.PutSession(session)
   138  
   139  	return fn(mm.GetCollection(session))
   140  }
   141  
   142  func (mm *Model) execute(fn func(c Collection) error) error {
   143  	session, err := mm.TakeSession()
   144  	if err != nil {
   145  		return err
   146  	}
   147  	defer mm.PutSession(session)
   148  
   149  	return fn(mm.GetCollection(session))
   150  }
   151  
   152  func (mm *Model) pipe(fn func(c Collection) Pipe) (Pipe, error) {
   153  	session, err := mm.TakeSession()
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	defer mm.PutSession(session)
   158  
   159  	return fn(mm.GetCollection(session)), nil
   160  }
   161  
   162  func (mm *Model) query(fn func(c Collection) Query) (Query, error) {
   163  	session, err := mm.TakeSession()
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	defer mm.PutSession(session)
   168  
   169  	return fn(mm.GetCollection(session)), nil
   170  }
   171  
   172  // WithTimeout customizes an operation with given timeout.
   173  func WithTimeout(timeout time.Duration) Option {
   174  	return func(opts *options) {
   175  		opts.timeout = timeout
   176  	}
   177  }