如何使用Go语言在MongoDB中以UUID类型存储数据?
解决Go操作MongoDB时UUID存储格式不匹配问题
问题原因
你在MongoDB控制台插入的UUID("xxx")本质是subtype为4的Binary数据,而使用github.com/google/uuid库的uuid.UUID类型时,Go的MongoDB驱动默认会把它序列化为subtype为0的通用二进制数据(即BinData(0, "...")),两种格式不兼容,导致跨控制台和Go代码的查询无法匹配。
解决方案
通过自定义UUID类型并实现BSON序列化/反序列化接口,让Go代码生成的UUID序列化为MongoDB兼容的subtype 4二进制格式,和控制台插入的UUID格式保持一致。
步骤1:自定义MongoDB兼容的UUID类型
package main import ( "context" "fmt" "log" "github.com/google/uuid" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // 自定义类型包装uuid.UUID,实现BSON序列化接口 type MongoDBUUID uuid.UUID // MarshalBSON 将MongoDBUUID序列化为MongoDB兼容的UUID格式(subtype 4) func (u MongoDBUUID) MarshalBSON() ([]byte, error) { binary := primitive.Binary{ Subtype: 4, // MongoDB UUID对应的subtype值 Data: []byte(u), } return bson.Marshal(binary) } // UnmarshalBSON 从MongoDB的UUID格式反序列化为MongoDBUUID func (u *MongoDBUUID) UnmarshalBSON(data []byte) error { var binary primitive.Binary if err := bson.Unmarshal(data, &binary); err != nil { return err } if binary.Subtype != 4 { return fmt.Errorf("无效的UUID subtype:%d", binary.Subtype) } copy((*u)[:], binary.Data) return nil }
步骤2:修改Person结构体使用自定义类型
type Person struct { Name string `bson:"name"` Sign MongoDBUUID `bson:"sign"` }
步骤3:插入文档
func main() { client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost:27017")) if err != nil { log.Fatal(err) } defer client.Disconnect(context.Background()) db := client.Database("mydatabase") collection := db.Collection("people") // 生成UUID并转为自定义类型 signUUID := uuid.New() person := Person{ Name: "John", Sign: MongoDBUUID(signUUID), } _, err = collection.InsertOne(context.Background(), person) if err != nil { log.Fatal(err) } fmt.Println("文档插入成功") }
验证效果
插入后在MongoDB控制台查看文档,sign字段会显示为UUID("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")格式,和你手动插入的完全一致。
控制台查询
使用你原来的查询语句即可匹配:
db.getCollection('people').find({"sign": UUID("32e79135-76c4-4682-80b2-8c813be9b792")})
Go代码查询
// 解析目标UUID字符串 targetUUIDStr := "32e79135-76c4-4682-80b2-8c813be9b792" targetUUID, err := uuid.Parse(targetUUIDStr) if err != nil { log.Fatal(err) } // 查询文档 var result Person err = collection.FindOne(context.Background(), bson.M{"sign": MongoDBUUID(targetUUID)}).Decode(&result) if err != nil { log.Fatal(err) } fmt.Printf("查询到的文档:%+v\n", result)
内容的提问来源于stack exchange,提问作者etroby
相关产品推荐
相关产品推荐

