MongoDB文档在Go的mongo-driver中返回键值对数组。

huangapple go评论69阅读模式
英文:

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 MongoDB文档在Go的mongo-driver中返回键值对数组。

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)

huangapple
  • 本文由 发表于 2022年11月13日 14:10:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/74418871.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定