gpt4 book ai didi

mongodb - 为什么json.RawMessage扩大mongoDb文档大小?

转载 作者:行者123 更新时间:2023-12-01 22:42:30 26 4
gpt4 key购买 nike

以下代码尝试通过go.mongodb.org/mongo-driver将新文档插入到mongoDB中

    data := "this is test string blablablablablablabla"
type Doc struct {
Version int "json:version, bson:version"
Data string "json:data, bson:data"
}
dd := Doc{Version: 21, Data: data}
dObj, _ := json.Marshal(dd)

queryFilter := bson.M{"version": 1}
update1 := bson.M{"$set": bson.M{"version": 1, "data": json.RawMessage(dObj)}}

// insert data with json.RawMessage
_, err := db.Mongo("test").Collection("test_doc1").UpdateOne(context.Background(), queryFilter, update1, options.Update().SetUpsert(true))
if err != nil {
fmt.Println("failed to insert doc1")
}

update2 := bson.M{"$set": bson.M{"version": 1, "data": (dObj)}}

// insert data without json.RawMessage
_, err = db.Mongo("test").Collection("test_doc2").UpdateOne(context.Background(), queryFilter, update2, options.Update().SetUpsert(true))
if err != nil {
fmt.Println("failed to insert doc2")
}
test_doc1的内容为 "data": json.RawMessage(dObj),而 test_doc2的内容为 "data": (dObj)

文件内容如下
db.test_doc1.find()
{ "_id" : ObjectId("5da164a950d625a5b2e5d23e"), "version" : 1, "data" : [ 123, 34, 86, 101, 114, 115, 105, 111, 110, 34, 58, 50, 49, 44, 34, 68, 97, 116, 97, 34, 58, 34, 116, 104, 105, 115, 32, 105, 115, 32, 116, 101, 115, 116, 32, 115, 116, 114, 105, 110, 103, 32, 98, 108, 97, 98, 108, 97, 98, 108, 97, 98, 108, 97, 98, 108, 97, 98, 108, 97, 98, 108, 97, 34, 125 ] }

db.test_doc2.find()
{ "_id" : ObjectId("5da164a950d625a5b2e5d249"), "version" : 1, "data" : BinData(0,"eyJWZXJzaW9uIjoyMSwiRGF0YSI6InRoaXMgaXMgdGVzdCBzdHJpbmcgYmxhYmxhYmxhYmxhYmxhYmxhYmxhIn0=") }

经过检查以上两个文件的大小
Object.bsonsize(db.test_doc2.findOne())
111

Object.bsonsize(db.test_doc1.findOne())
556
test_doc1的大小大于 test_doc2的大小。为什么?

bson doc

数组-数组的文档是一个普通的BSON文档,具有键的整数值,从0开始,并依次连续。例如,数组['red','blue']将被编码为文档{'0':'red','1':'blue'}。键必须按升序排列。

Bson阵列可以占用更多磁盘空间吗?我对吗?

MongoDB版本:4.0

最佳答案

test_doc1使用的json.RawMessage本质上是[]byte,因此它被存储为代表字符串(文档的原始表示)的整数数组。

test_doc2将数据存储为二进制数据,这是一种更紧凑的形式。

Go Mongo驱动程序对json编码数据使用WriteBinaryWithSubtype方法,但对WriteArray使用RawMessage

区别在于mongo端用于存储这些数据的数据类型。一种是将 byte slice 存储为整数数组,另一种是将数据存储为具有子类型的二进制。与整数相比,二进制形式占用的空间更少。

深入研究,我发现Go驱动程序使用注册表来确定应如何将值编码为BSON。有一种专用于 byte slice 的方法。

// ByteSliceEncodeValue is the ValueEncoderFunc for []byte.
func (dve DefaultValueEncoders) ByteSliceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {

此方法使用 WriteBinary()方法将 byte slice 编码为二进制数据。

如果有自定义类型(即使其下面是 []byte),则将其视为 slice 类型并触发 slice 的“默认编码器”。
// SliceEncodeValue is the ValueEncoderFunc for slice types.
func (dve DefaultValueEncoders) SliceEncodeValue(ec EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {

此方法依次使用 WriteArray()方法。

摘要: json.Marshal调用直接使用 []byte类型,因此它们被视为bson二进制类型并以紧凑的二进制形式存储。即使内部将数据存储为 json.RawMessage[]byte也被视为一个片,一个整数片,因此在mongo中作为一个整数数组存储。

关于mongodb - 为什么json.RawMessage扩大mongoDb文档大小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58351694/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com