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 }