-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.go
72 lines (58 loc) · 1.85 KB
/
index.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package xmongo
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
// doc: https://www.mongodb.com/docs/v7.0/tutorial/manage-indexes/#minimize-performance-impact-with-a-temporary-index
func ModifyIndex(ctx context.Context, collection *mongo.Collection, name string, newIndex mongo.IndexModel) error {
// 0. find the existing index
indexes, err := collection.Indexes().ListSpecifications(ctx, options.ListIndexes())
if err != nil {
return fmt.Errorf("list indexes: %w", err)
}
var existingIndex *mongo.IndexSpecification
for _, i := range indexes {
if i.Name == name {
existingIndex = i
}
}
if existingIndex == nil {
return fmt.Errorf("index %s not found", name)
}
rawkeys, err := existingIndex.KeysDocument.Elements()
if err != nil {
return fmt.Errorf("keys document: %w", err)
}
var keys []bson.E
for _, key := range rawkeys {
keys = append(keys, bson.E{Key: key.Key(), Value: 1})
}
const dummyField = "_tmp_dummy_field"
keys = append(keys, bson.E{Key: dummyField, Value: 1})
tmpIndexName := fmt.Sprintf("temp_index_%s", name)
// 1. create a temporary index
if _, err := collection.Indexes().CreateOne(ctx, mongo.IndexModel{
Keys: keys,
Options: &options.IndexOptions{
Name: &tmpIndexName,
},
}); err != nil {
return fmt.Errorf("create temp index: %w", err)
}
// 2. drop the existing index
if _, err := collection.Indexes().DropOne(ctx, name); err != nil {
return fmt.Errorf("drop index %s: %w", name, err)
}
// 3. create the new index
if _, err := collection.Indexes().CreateOne(ctx, newIndex); err != nil {
return fmt.Errorf("create new index: %w", err)
}
// 4. drop the temporary index
if _, err := collection.Indexes().DropOne(ctx, tmpIndexName); err != nil {
return fmt.Errorf("drop temp index: %w", err)
}
return nil
}