如何使用mongo-go-Driver将BSON文档解组为类型M

exdqitrt  于 2022-09-18  发布在  Go
关注(0)|答案(3)|浏览(261)

根据mongo-driver https://godoc.org/go.mongodb.org/mongo-driver/bson中的文档,将bson解组到接口{}中会将值默认为D

1.解组时,接口类型为{}的字段会跟在上面列出的D/M类型Map之后。解组到接口{}字段中的BSON文档将被解组为D。

如果我在数据库中将一个对象存储为:

"data": {
   "property1": "value1",
   "property2": "value2",
}

当我检索此数据时使用“

var result interface{}
err = collection.FindOne(ctx, filter).Decode(&result)

它会变成:

"data": [
   {"Key": "property1", "Value": "value1"},
   {"Key": "property2", "Value": "value2"}
]

与文档相符,类型D是密钥值的一部分

我的问题是,有没有一种方法可以改变这种行为,使其将数据解组为M?

我的应用程序不知道数据的实际结构。它只接受json作为输入并存储在db中,所以在取消取数时必须使用接口{}作为类型。如果它以Map的形式存储在数据库中,它应该以相同的方式检索数据。

xcitsw88

xcitsw881#

这是默认功能,如果您传递interface{},然后将其解组为bson.D,则无法更改。但您可以通过这种方式将bson.D转换为bson.M

resultMap := result.(bson.D).Map()

或者,您可以在解组时直接使用bson.M变量。

var result bson.M
err = collection.FindOne(ctx, filter).Decode(&result)
t9eec4r0

t9eec4r02#

解组为bson.M类型的变量:

var result bson.M
err = collection.FindOne(ctx, filter).Decode(&result)

因为bson.M类型满足接口interface{}(和所有类型一样),所以您可以在使用interface{}值的任何地方使用bson.M值。

Run it on the playground

6tdlim6h

6tdlim6h3#

我在使用opa库时遇到了这个问题。由于某些原因,OPA模块没有为嵌套的json值返回正确的评估。根据:https://www.mongodb.com/community/forums/t/storing-deeply-nested-data/9985/3
在内部,bson.D类型表示为具有名为key和value(...)的字段的结构的片段与bson.D不同,bson.m类型是简单的map[字符串]接口{},因此标准库json函数可以处理它。

我已经开始更深入地研究这件事。正如前面有人提到的,bson解组的默认格式是bson.dtype。当我们像这样解组时,我们得到:unmarshaling into interface{}

但是,当我们强制将数据解组到bson.M中时,而不仅仅是接口{}或bson.d,我们得到:unmarshaling into bson.M

我们可以使用.map方法将bson.D转换为bson.M,但最终并不相同:bson.D converted to bson.M

在这两个场景中,嵌套字段“baz”的类型不同。

这解释了.map方法的当前实现,它当前看起来如下所示:

func (d D) Map() M {
    m := make(M, len(d))
    for _, e := range d {
        m[e.Key] = e.Value
    }
    return m
}

看起来,使用.map方法将bson.D转换为bson.M与直接将其解组为bson.M不同。

相关问题