From 83e45dfc0e30731c3b60d936e5353ed0a5d3395f Mon Sep 17 00:00:00 2001 From: Marvin Zhang Date: Wed, 11 Dec 2024 11:45:08 +0800 Subject: [PATCH] fix: duplicated index recreation --- core/models/common/index_utils.go | 61 +++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/core/models/common/index_utils.go b/core/models/common/index_utils.go index 93a1f89e..0a0028a2 100644 --- a/core/models/common/index_utils.go +++ b/core/models/common/index_utils.go @@ -1,13 +1,68 @@ package common import ( + "encoding/json" "fmt" - "github.com/apex/log" "github.com/crawlab-team/crawlab/db/mongo" + "go.mongodb.org/mongo-driver/bson" mongo2 "go.mongodb.org/mongo-driver/mongo" ) +// getIndexKeyString converts index keys to a consistent string representation +func getIndexKeyString(key interface{}) string { + switch v := key.(type) { + case mongo2.IndexModel: + return normalizeIndexKey(v.Keys) + default: + return normalizeIndexKey(key) + } +} + +// normalizeIndexKey converts an index key to a standardized string representation +func normalizeIndexKey(key interface{}) string { + // Convert to bson.D to maintain order + var doc bson.D + + switch v := key.(type) { + case bson.D: + doc = v + default: + // Convert to JSON bytes first + jsonBytes, err := json.Marshal(key) + if err != nil { + return fmt.Sprintf("%v", key) + } + + // Try to unmarshal as array of key-value pairs first + var keyArray []struct { + Key string `json:"Key"` + Value interface{} `json:"Value"` + } + if err := json.Unmarshal(jsonBytes, &keyArray); err == nil { + // Convert array format to bson.D + doc = make(bson.D, len(keyArray)) + for i, kv := range keyArray { + doc[i] = bson.E{Key: kv.Key, Value: kv.Value} + } + } else { + // Try to unmarshal as regular map + if err := bson.UnmarshalExtJSON(jsonBytes, true, &doc); err != nil { + return string(jsonBytes) + } + } + } + + // Convert bson.D to consistent string representation + pairs := make([]string, 0, len(doc)) + for _, elem := range doc { + pairs = append(pairs, fmt.Sprintf("%q:%v", elem.Key, elem.Value)) + } + + res, _ := bson.Marshal(pairs) + return string(res) +} + func RecreateIndexes(col *mongo.Col, desiredIndexes []mongo2.IndexModel) { existingIndexes, err := col.ListIndexes() if err != nil { @@ -24,7 +79,7 @@ func RecreateIndexes(col *mongo.Col, desiredIndexes []mongo2.IndexModel) { name, ok := idx["name"].(string) if ok && name != "_id_" { if key, ok := idx["key"]; ok { - keyStr := fmt.Sprintf("%v", key) + keyStr := getIndexKeyString(key) existingKeys[keyStr] = true } } @@ -32,7 +87,7 @@ func RecreateIndexes(col *mongo.Col, desiredIndexes []mongo2.IndexModel) { // Check if desired indexes exist for _, idx := range desiredIndexes { - keyStr := fmt.Sprintf("%v", idx.Keys) + keyStr := getIndexKeyString(idx.Keys) if !existingKeys[keyStr] { needsUpdate = true break