英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论