英文:
MongoDB document returns array of key value pair in go mongo-driver
问题
在我们的代码库中,我们有一个合并两个结构体的函数,类似下面的样子。
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)
// 上面的代码将两个结构体合并
此外,目前我们的所有结构体只有json标签,没有bson标签,我们是否需要在所有地方添加bson标签?
例如:
type someStruct struct {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
Field3 interface{} `json:"field3"`
}
在上面的someStruct中,我们还有接口类型的字段!
现在我面临的问题是,无论在哪里合并结构体,我在mongoDB中看到的对象数据都显示为键值对的数组,类似下面的样子:
"studentDetails" : [
{
"Key" : "Details",
"Value" : [
[
{
"Key" : "Name",
"Value" : "Bob"
},
{
"Value" : "21",
"Key" : "Age"
}
]
]
},
{
"Key" : "Enrolled",
"Value" : false
}
],
但是我希望它显示为下面的样子,而不是键值对的数组。
"studentDetails" : {
"Details" : [
{
"name" : "serverdr",
"age" : 21
},
{
"Enrolled" : false
}
],
}
在我们旧的全局mgo驱动中,对象以上述方式显示。但是使用新的go-mongo驱动时,当我们使用CombineStruct()函数合并两个结构体时,它会显示为键值对的数组。
英文:
In our code base we have a function which merges two structs , something like below .
func CombineStruct(s1 interface{}, s2 interface{}) error {
data, err := json.Marshal(s1)
if err != nil {
return err
}
return json.Unmarshal(data, s2)
}
We use the above func to combine two structs something like below .
m := model.SomeModel{}
CombineStruct(someStruct, &m)
//above line merges two structs
Also currently all our structs has only json tags not bson tags yet, should we need to add bson tags in all the places ?
for ex :
type someStruct struct {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
Field3 interface{} `json:"field2"`
}
In the above someStruct we have fields of type interface too!
Now the issue that i'm facing is wherever we combine the struct I see those object data in mongoDB as array of key-value pair something like below :
"studentDetails" : [
{
"Key" : "Details",
"Value" : [
[
{
"Key" : "Name",
"Value" : "Bob"
},
{
"Value" : "21",
"Key" : "Age"
}
]
]
},
{
"Key" : "Enrolled",
"Value" : false
}
],
But I want this to be displayed like something like below . Not like key-value pair.
"studentDetails" : {
"Details" : [
{
"name" : "serverdr",
"age" : 21
},
{
"Enrolled" : false
}
],
It was displaying objects like above way in our old global sing mgo driver .But using the new go-mongo driver when we combine two structs using the CombineStruct() function it displays as array of key value pair.
答案1
得分: 2
我尝试了下面的代码,结果非常好:)
问题的关键在于mongo-driver默认将类型为interface{}的结构体反序列化为bson.D,而mgo-driver默认为bson.M。
因此,在尝试与mongo-db建立连接时,我们需要添加以下代码,将SetRegistry()选项作为clientOpts,以映射旧的mgo行为,使得mongo-driver在反序列化类型为interface{}的结构体时默认为bson.M,这样就不会将值显示为键值对形式。
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)
英文:
I tried something like below and that worked like a charm ![]()
So basically what's the problem is that the mongo-driver defaults to unmarshalling as bson.D for structs of type interface{} where as mgo mgo-driver defaults to bson.M .
So we will have to add the below code while trying to establish connection with mongo-db , SetRegistry() options as clientOpts To map the old mgo behavior, so that mongo-driver defaults to bson.M while unmarshalling structs of type interface{} , and this should not display the values back as key-value pair
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论