在我们的代码库中,我们有一个合并两个结构的函数,如下所示。
func CombineStruct(s1 interface{}, s2 interface{}) error {
data, err := json.Marshal(s1)
if err != nil {
return err
}
return json.Unmarshal(data, s2)
}
我们使用上面的函数来组合两个结构,如下所示。
m := model.SomeModel{}
CombineStruct(someStruct, &m)
//above line merges two structs
目前我们所有的结构体都只有
json
标签,还没有 bson
标签,我们是否需要在所有地方添加 bson
标签?
for ex :
type someStruct struct {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
Field3 interface{} `json:"field2"`
}
在上面
someStruct
我们也有接口类型的字段!
现在我面临的问题是,无论我们在哪里组合结构,我都会在
mongoDB
中看到这些对象数据作为 key-value
对的数组,如下所示:
"studentDetails" : [
{
"Key" : "Details",
"Value" : [
[
{
"Key" : "Name",
"Value" : "Bob"
},
{
"Value" : "21",
"Key" : "Age"
}
]
]
},
{
"Key" : "Enrolled",
"Value" : false
}
],
但我希望它显示如下。不像
key-value
对。
"studentDetails" : {
"Details" : [
{
"name" : "serverdr",
"age" : 21
},
{
"Enrolled" : false
}
],
它在我们旧的全局 sing mgo 驱动程序中以上述方式显示对象。但是,当我们使用 CombineStruct()
函数组合两个结构时,使用新的
go-mongo驱动程序,它
displays
作为键值对数组。
我尝试了如下的方法,效果非常好:)
所以基本上问题是 mongo-driver 默认为
bson.D
类型的结构解组为 interface{}
,其中 mgo
mgo-driver 默认为 bson.M
.
因此,我们必须在尝试与
mongo-db
、 SetRegistry()
选项建立连接时添加以下代码作为 clientOpts
来映射旧的 mgo 行为,以便在解组类型结构时 mongo-driver
默认为 bson.M
interface{}
,并且这不应将值显示为 key-value
对
tM := reflect.TypeOf(bson.M{})
reg := bson.NewRegistryBuilder().RegisterTypeMapEntry(bsontype.EmbeddedDocument, tM).Build()
clientOpts := options.Client().ApplyURI(SOMEURI).SetAuth(authVal).SetRegistry(reg)
client, err := mongo.Connect(ctx, clientOpts)
获取集合或数据库时,您可以添加选项来告诉 mongo 以提供的数据类型提取数据。
opts := &options.CollectionOptions{
BSONOptions: &options.BSONOptions{
DefaultDocumentM: true,
},
}
collection := database.Collection(collection_name, opts)
这里它将解组 bson.M 类型的数据,我们可以轻松地将其用作地图。