1
2
3
4
5
6
7 package mongo
8
9 import (
10 "context"
11 "fmt"
12 "strconv"
13
14 "go.mongodb.org/mongo-driver/bson"
15 "go.mongodb.org/mongo-driver/mongo/options"
16 "go.mongodb.org/mongo-driver/mongo/writeconcern"
17 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore"
18 "go.mongodb.org/mongo-driver/x/mongo/driver"
19 "go.mongodb.org/mongo-driver/x/mongo/driver/operation"
20 "go.mongodb.org/mongo-driver/x/mongo/driver/session"
21 )
22
23
24
25 type SearchIndexView struct {
26 coll *Collection
27 }
28
29
30 type SearchIndexModel struct {
31
32
33 Definition interface{}
34
35
36 Options *options.SearchIndexesOptions
37 }
38
39
40
41
42
43
44
45 func (siv SearchIndexView) List(
46 ctx context.Context,
47 searchIdxOpts *options.SearchIndexesOptions,
48 opts ...*options.ListSearchIndexesOptions,
49 ) (*Cursor, error) {
50 if ctx == nil {
51 ctx = context.Background()
52 }
53
54 index := bson.D{}
55 if searchIdxOpts != nil && searchIdxOpts.Name != nil {
56 index = bson.D{{"name", *searchIdxOpts.Name}}
57 }
58
59 aggregateOpts := make([]*options.AggregateOptions, len(opts))
60 for i, opt := range opts {
61 aggregateOpts[i] = opt.AggregateOpts
62 }
63
64 return siv.coll.Aggregate(ctx, Pipeline{{{"$listSearchIndexes", index}}}, aggregateOpts...)
65 }
66
67
68
69 func (siv SearchIndexView) CreateOne(
70 ctx context.Context,
71 model SearchIndexModel,
72 opts ...*options.CreateSearchIndexesOptions,
73 ) (string, error) {
74 names, err := siv.CreateMany(ctx, []SearchIndexModel{model}, opts...)
75 if err != nil {
76 return "", err
77 }
78
79 return names[0], nil
80 }
81
82
83
84
85
86
87
88
89 func (siv SearchIndexView) CreateMany(
90 ctx context.Context,
91 models []SearchIndexModel,
92 _ ...*options.CreateSearchIndexesOptions,
93 ) ([]string, error) {
94 var indexes bsoncore.Document
95 aidx, indexes := bsoncore.AppendArrayStart(indexes)
96
97 for i, model := range models {
98 if model.Definition == nil {
99 return nil, fmt.Errorf("search index model definition cannot be nil")
100 }
101
102 definition, err := marshal(model.Definition, siv.coll.bsonOpts, siv.coll.registry)
103 if err != nil {
104 return nil, err
105 }
106
107 var iidx int32
108 iidx, indexes = bsoncore.AppendDocumentElementStart(indexes, strconv.Itoa(i))
109 if model.Options != nil && model.Options.Name != nil {
110 indexes = bsoncore.AppendStringElement(indexes, "name", *model.Options.Name)
111 }
112 indexes = bsoncore.AppendDocumentElement(indexes, "definition", definition)
113
114 indexes, err = bsoncore.AppendDocumentEnd(indexes, iidx)
115 if err != nil {
116 return nil, err
117 }
118 }
119
120 indexes, err := bsoncore.AppendArrayEnd(indexes, aidx)
121 if err != nil {
122 return nil, err
123 }
124
125 sess := sessionFromContext(ctx)
126
127 if sess == nil && siv.coll.client.sessionPool != nil {
128 sess = session.NewImplicitClientSession(siv.coll.client.sessionPool, siv.coll.client.id)
129 defer sess.EndSession()
130 }
131
132 err = siv.coll.client.validSession(sess)
133 if err != nil {
134 return nil, err
135 }
136
137 wc := siv.coll.writeConcern
138 if sess.TransactionRunning() {
139 wc = nil
140 }
141 if !writeconcern.AckWrite(wc) {
142 sess = nil
143 }
144
145 selector := makePinnedSelector(sess, siv.coll.writeSelector)
146
147 op := operation.NewCreateSearchIndexes(indexes).
148 Session(sess).WriteConcern(wc).ClusterClock(siv.coll.client.clock).
149 Database(siv.coll.db.name).Collection(siv.coll.name).CommandMonitor(siv.coll.client.monitor).
150 Deployment(siv.coll.client.deployment).ServerSelector(selector).ServerAPI(siv.coll.client.serverAPI).
151 Timeout(siv.coll.client.timeout)
152
153 err = op.Execute(ctx)
154 if err != nil {
155 _, err = processWriteError(err)
156 return nil, err
157 }
158
159 indexesCreated := op.Result().IndexesCreated
160 names := make([]string, 0, len(indexesCreated))
161 for _, index := range indexesCreated {
162 names = append(names, index.Name)
163 }
164
165 return names, nil
166 }
167
168
169
170
171
172
173
174
175 func (siv SearchIndexView) DropOne(
176 ctx context.Context,
177 name string,
178 _ ...*options.DropSearchIndexOptions,
179 ) error {
180 if name == "*" {
181 return ErrMultipleIndexDrop
182 }
183
184 if ctx == nil {
185 ctx = context.Background()
186 }
187
188 sess := sessionFromContext(ctx)
189 if sess == nil && siv.coll.client.sessionPool != nil {
190 sess = session.NewImplicitClientSession(siv.coll.client.sessionPool, siv.coll.client.id)
191 defer sess.EndSession()
192 }
193
194 err := siv.coll.client.validSession(sess)
195 if err != nil {
196 return err
197 }
198
199 wc := siv.coll.writeConcern
200 if sess.TransactionRunning() {
201 wc = nil
202 }
203 if !writeconcern.AckWrite(wc) {
204 sess = nil
205 }
206
207 selector := makePinnedSelector(sess, siv.coll.writeSelector)
208
209 op := operation.NewDropSearchIndex(name).
210 Session(sess).WriteConcern(wc).CommandMonitor(siv.coll.client.monitor).
211 ServerSelector(selector).ClusterClock(siv.coll.client.clock).
212 Database(siv.coll.db.name).Collection(siv.coll.name).
213 Deployment(siv.coll.client.deployment).ServerAPI(siv.coll.client.serverAPI).
214 Timeout(siv.coll.client.timeout)
215
216 err = op.Execute(ctx)
217 if de, ok := err.(driver.Error); ok && de.NamespaceNotFound() {
218 return nil
219 }
220 return err
221 }
222
223
224
225
226
227
228
229
230
231 func (siv SearchIndexView) UpdateOne(
232 ctx context.Context,
233 name string,
234 definition interface{},
235 _ ...*options.UpdateSearchIndexOptions,
236 ) error {
237 if definition == nil {
238 return fmt.Errorf("search index definition cannot be nil")
239 }
240
241 indexDefinition, err := marshal(definition, siv.coll.bsonOpts, siv.coll.registry)
242 if err != nil {
243 return err
244 }
245
246 if ctx == nil {
247 ctx = context.Background()
248 }
249
250 sess := sessionFromContext(ctx)
251 if sess == nil && siv.coll.client.sessionPool != nil {
252 sess = session.NewImplicitClientSession(siv.coll.client.sessionPool, siv.coll.client.id)
253 defer sess.EndSession()
254 }
255
256 err = siv.coll.client.validSession(sess)
257 if err != nil {
258 return err
259 }
260
261 wc := siv.coll.writeConcern
262 if sess.TransactionRunning() {
263 wc = nil
264 }
265 if !writeconcern.AckWrite(wc) {
266 sess = nil
267 }
268
269 selector := makePinnedSelector(sess, siv.coll.writeSelector)
270
271 op := operation.NewUpdateSearchIndex(name, indexDefinition).
272 Session(sess).WriteConcern(wc).CommandMonitor(siv.coll.client.monitor).
273 ServerSelector(selector).ClusterClock(siv.coll.client.clock).
274 Database(siv.coll.db.name).Collection(siv.coll.name).
275 Deployment(siv.coll.client.deployment).ServerAPI(siv.coll.client.serverAPI).
276 Timeout(siv.coll.client.timeout)
277
278 return op.Execute(ctx)
279 }
280
View as plain text