github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/mongo/collections.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package mongo
     5  
     6  import (
     7  	"time"
     8  
     9  	"github.com/juju/mgo/v3"
    10  )
    11  
    12  // CollectionFromName returns a named collection on the specified database,
    13  // initialised with a new session. Also returned is a close function which
    14  // must be called when the collection is no longer required.
    15  func CollectionFromName(db *mgo.Database, coll string) (Collection, func()) {
    16  	session := db.Session.Copy()
    17  	newColl := db.C(coll).With(session)
    18  	return WrapCollection(newColl), session.Close
    19  }
    20  
    21  // Collection imperfectly insulates clients from the capacity to write to
    22  // MongoDB. Query results can still be used to write; and the Writeable
    23  // method exposes the underlying *mgo.Collection when absolutely required;
    24  // but the general expectation in juju is that writes will occur only via
    25  // mgo/txn, and any layer-skipping is done only in exceptional and well-
    26  // supported circumstances.
    27  type Collection interface {
    28  
    29  	// Name returns the name of the collection.
    30  	Name() string
    31  
    32  	// Count, Find, and FindId methods act as documented for *mgo.Collection.
    33  	Count() (int, error)
    34  	Find(query interface{}) Query
    35  	FindId(id interface{}) Query
    36  	Pipe(pipeline interface{}) *mgo.Pipe
    37  
    38  	// Writeable gives access to methods that enable direct DB access. It
    39  	// should be used with judicious care, and for only the best of reasons.
    40  	Writeable() WriteCollection
    41  }
    42  
    43  // WriteCollection allows read/write access to a MongoDB collection.
    44  type WriteCollection interface {
    45  	Collection
    46  
    47  	// Underlying returns the underlying *mgo.Collection.
    48  	Underlying() *mgo.Collection
    49  
    50  	// All other methods act as documented for *mgo.Collection.
    51  	Insert(docs ...interface{}) error
    52  	Upsert(selector interface{}, update interface{}) (info *mgo.ChangeInfo, err error)
    53  	UpsertId(id interface{}, update interface{}) (info *mgo.ChangeInfo, err error)
    54  	Update(selector interface{}, update interface{}) error
    55  	UpdateId(id interface{}, update interface{}) error
    56  	Remove(sel interface{}) error
    57  	RemoveId(id interface{}) error
    58  	RemoveAll(sel interface{}) (*mgo.ChangeInfo, error)
    59  }
    60  
    61  // Query allows access to a portion of a MongoDB collection.
    62  type Query interface {
    63  	All(result interface{}) error
    64  	Apply(change mgo.Change, result interface{}) (info *mgo.ChangeInfo, err error)
    65  	Batch(n int) Query
    66  	Comment(comment string) Query
    67  	Count() (n int, err error)
    68  	Distinct(key string, result interface{}) error
    69  	Explain(result interface{}) error
    70  	For(result interface{}, f func() error) error
    71  	Hint(indexKey ...string) Query
    72  	Iter() Iterator
    73  	Limit(n int) Query
    74  	LogReplay() Query
    75  	MapReduce(job *mgo.MapReduce, result interface{}) (info *mgo.MapReduceInfo, err error)
    76  	One(result interface{}) (err error)
    77  	Prefetch(p float64) Query
    78  	Select(selector interface{}) Query
    79  	SetMaxScan(n int) Query
    80  	SetMaxTime(d time.Duration) Query
    81  	Skip(n int) Query
    82  	Snapshot() Query
    83  	Sort(fields ...string) Query
    84  	Tail(timeout time.Duration) *mgo.Iter
    85  }
    86  
    87  // Iterator defines the parts of the mgo.Iter that we use - this
    88  // interface allows us to switch out the querying for testing.
    89  type Iterator interface {
    90  	Next(interface{}) bool
    91  	Timeout() bool
    92  	Close() error
    93  }
    94  
    95  // WrapCollection returns a Collection that wraps the supplied *mgo.Collection.
    96  func WrapCollection(coll *mgo.Collection) Collection {
    97  	return collectionWrapper{coll}
    98  }
    99  
   100  // collectionWrapper wraps a *mgo.Collection and implements Collection and
   101  // WriteCollection.
   102  type collectionWrapper struct {
   103  	*mgo.Collection
   104  }
   105  
   106  // Name is part of the Collection interface.
   107  func (cw collectionWrapper) Name() string {
   108  	return cw.Collection.Name
   109  }
   110  
   111  // Find is part of the Collection interface.
   112  func (cw collectionWrapper) Find(query interface{}) Query {
   113  	return queryWrapper{cw.Collection.Find(query)}
   114  }
   115  
   116  // Pipe is part of the Collection interface
   117  func (cw collectionWrapper) Pipe(pipeline interface{}) *mgo.Pipe {
   118  	return cw.Collection.Pipe(pipeline)
   119  }
   120  
   121  // FindId is part of the Collection interface.
   122  func (cw collectionWrapper) FindId(id interface{}) Query {
   123  	return queryWrapper{cw.Collection.FindId(id)}
   124  }
   125  
   126  // Writeable is part of the Collection interface.
   127  func (cw collectionWrapper) Writeable() WriteCollection {
   128  	return cw
   129  }
   130  
   131  // Underlying is part of the WriteCollection interface.
   132  func (cw collectionWrapper) Underlying() *mgo.Collection {
   133  	return cw.Collection
   134  }
   135  
   136  type queryWrapper struct {
   137  	*mgo.Query
   138  }
   139  
   140  func (qw queryWrapper) Batch(n int) Query {
   141  	return queryWrapper{qw.Query.Batch(n)}
   142  }
   143  
   144  func (qw queryWrapper) Comment(comment string) Query {
   145  	return queryWrapper{qw.Query.Comment(comment)}
   146  }
   147  
   148  func (qw queryWrapper) Hint(indexKey ...string) Query {
   149  	return queryWrapper{qw.Query.Hint(indexKey...)}
   150  }
   151  
   152  func (qw queryWrapper) Limit(n int) Query {
   153  	return queryWrapper{qw.Query.Limit(n)}
   154  }
   155  
   156  func (qw queryWrapper) LogReplay() Query {
   157  	return queryWrapper{qw.Query.LogReplay()}
   158  }
   159  
   160  func (qw queryWrapper) Prefetch(p float64) Query {
   161  	return queryWrapper{qw.Query.Prefetch(p)}
   162  }
   163  
   164  func (qw queryWrapper) Select(selector interface{}) Query {
   165  	return queryWrapper{qw.Query.Select(selector)}
   166  }
   167  
   168  func (qw queryWrapper) SetMaxScan(n int) Query {
   169  	return queryWrapper{qw.Query.SetMaxScan(n)}
   170  }
   171  
   172  func (qw queryWrapper) SetMaxTime(d time.Duration) Query {
   173  	return queryWrapper{qw.Query.SetMaxTime(d)}
   174  }
   175  
   176  func (qw queryWrapper) Skip(n int) Query {
   177  	return queryWrapper{qw.Query.Skip(n)}
   178  }
   179  
   180  func (qw queryWrapper) Snapshot() Query {
   181  	return queryWrapper{qw.Query.Snapshot()}
   182  }
   183  
   184  func (qw queryWrapper) Sort(fields ...string) Query {
   185  	return queryWrapper{qw.Query.Sort(fields...)}
   186  }
   187  
   188  func (qw queryWrapper) Iter() Iterator {
   189  	return qw.Query.Iter()
   190  }