文档菜单
文档首页
/ / /
Go 驱动
/

处理BSON

本页内容

  • 概述
  • 数据类型
  • 结构标签
  • BSON选项
  • 反序列化

在本指南中,您可以了解Go驱动程序如何处理BSON和Go类型之间的转换。将Go类型转换为BSON的过程称为序列化,而相反的过程称为反序列化

以下各节解释了Go驱动程序如何表示BSON数据以及如何调整默认的序列化和反序列化行为。

MongoDB以二进制形式存储文档,称为BSON,它允许轻松灵活地处理数据。

Go驱动程序为处理BSON数据提供了四种主要类型

  • D:BSON文档的有序表示(切片)

  • M:BSON文档的无序表示(映射)

  • A:BSON数组的有序表示

  • E:D类型中的一个单一元素

以下示例演示了如何使用bson.D类型构建查询过滤器,以匹配值为大于100的文档中的quantity字段

filter := bson.D{{"quantity", bson.D{{"$gt", 100}}}}

要了解Go驱动程序如何处理BSON数据,请参阅bson包API文档。

在Go中,struct 是由声明的数据类型组成的字段集合。您可以通过使用 struct 标签 来修改 struct 字段的默认序列化和反序列化行为,struct 标签是附加到 struct 字段上的可选元数据。struct 标签最常见的使用是指定与 struct 字段相对应的 BSON 文档中的字段名称。以下表格描述了在 Go 驱动程序中可以使用的附加 struct 标签

Struct 标签
描述
omitempty
如果字段设置为与字段类型对应的零值,则不会对其进行序列化。
minsize
如果字段类型为 int64uintuint32uint64,并且字段的值可以适合有符号 int32,则该字段将序列化为 BSON int32 而不是 BSON int64。如果值无法适合有符号 int32,则忽略此标签。
truncate
如果字段类型为非浮点数值类型,则将反序列化到该字段的 BSON 双精度浮点数截断到小数点。
inline
如果字段类型为 struct 或 map 字段,则字段在序列化时将扁平化,在反序列化时将取消扁平化。

如果您未指定 struct 标签,Go 驱动程序将根据以下规则序列化 struct

  1. 驱动程序仅序列化和反序列化导出字段。

  2. 驱动程序使用对应 struct 字段的字母小写来生成 BSON 键。

  3. 驱动程序将内嵌的 struct 字段序列化为子文档。每个键是该字段类型的字母小写。

  4. 如果指针非空,驱动程序将指针字段序列化为基础类型。如果指针为空,驱动程序将其序列化为 BSON null 值。

  5. 在反序列化时,Go 驱动程序遵循 这些 D/M 类型映射 来处理类型为 interface{} 的字段。驱动程序将反序列化到 interface{} 字段的 BSON 文档作为 D 类型。

以下示例演示了 Go 驱动程序如何序列化具有各种 struct 标签的 struct

type Address struct {
Street string
City string
State string
}
type Student struct {
FirstName string `bson:"first_name,omitempty"`
LastName string `bson:"last_name,omitempty"`
Address Address `bson:"inline"`
Age int
}
coll := client.Database("db").Collection("students")
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
_, err = coll.InsertOne(context.TODO(), student1)

相应的 BSON 表示形式如下

{
"_id" : ObjectId("..."),
"first_name" : "Arthur",
"street" : "1 Lakewood Way",
"city" : "Elwood City",
"state" : "PA",
"age" : 8
}

在这个示例中,结构体标签使驱动程序

  • 设置自定义的BSON字段名,例如 first_name

  • 省略空的 LastName 字段

  • 将嵌套的结构体扁平化,并将所有字段提升到顶级

以下示例演示了Go驱动程序如何对没有结构体标签的结构体进行序列化

type Address struct {
Street string
City string
State string
}
type Student struct {
FirstName string
LastName string
Address Address
Age int
}
coll := client.Database("db").Collection("students")
address1 := Address{ "1 Lakewood Way", "Elwood City", "PA" }
student1 := Student{ FirstName : "Arthur", Address : address1, Age : 8}
_, err = coll.InsertOne(context.TODO(), student1)

相应的 BSON 表示形式如下

{
"_id" : ObjectId("..."),
"firstname" : "Arthur",
"lastname" : "",
"address": {
"street" : "1 Lakewood Way",
"city" : "Elwood City",
"state" : "PA"
},
"age" : 8
}

没有结构体标签,驱动程序

  • 将结构体字段的下划线形式作为BSON字段名

  • 包括一个空的 lastname 字段

  • Address 字段作为嵌套值存储

您可以通过指定BSON选项来调整您的 Client 实例的序列化和反序列化行为。要在您的 Client 上设置BSON选项,创建并配置一个 BSONOptions 实例。

此示例执行以下操作

  • 通过配置以下设置创建一个 BSONOptions 实例

    • UseJSONStructTags 字段设置为 true,这指示驱动程序在未指定 "bson" 结构体标签的情况下使用 "json" 结构体标签

    • NilSliceAsEmpty 字段设置为 true,这指示驱动程序将 nil Go 切片序列化为空的BSON数组

  • BSONOptions 实例传递给 SetBSONOptions() 辅助方法以指定 ClientOptions 实例

  • 创建一个 Client 以应用指定的BSON序列化和反序列化行为

bsonOpts := &options.BSONOptions {
UseJSONStructTags: true,
NilSliceAsEmpty: true,
}
clientOpts := options.Client().
ApplyURI("<connection string>").
SetBSONOptions(bsonOpts)
client, err := mongo.Connect(context.TODO(), clientOpts)

提示

要了解更多关于 BSONOptions 类型的信息,请参阅BSONOptions API 文档。要查看指定 BSONOptions 实例并使用这些选项创建客户端的示例,请参阅Connect() BSONOptions 示例。

您可以使用 FindOne 方法的结果或任何 *mongo.Cursor 实例上的 Decode() 方法来反序列化 BSON 文档。

Decode() 方法返回一个包含以下值的 error 类型:

  • nil 如果文档与您的查询匹配,并且检索和反序列化文档时没有错误。

  • 如果驱动程序检索了您的文档但无法反序列化您的结果,则 Decode() 方法返回反序列化错误。

  • 如果在执行FindOne()方法时检索文档出现错误,则该错误会传播到Decode()方法,并且Decode()方法会返回错误。

当在由FindOne()方法返回的SingleResult类型上使用时,如果查询过滤器没有匹配到文档,Decode()也可以返回ErrNoDocuments错误。

以下示例演示了如何使用Decode()方法来反序列化和读取简单的FindOne()操作的结果

coll := client.Database("db").Collection("students")
filter := bson.D{{"age", 8}}
var result bson.D
err := coll.FindOne(context.TODO(), filter).Decode(&result)
fmt.Println(result)
[{_id ObjectID("...")} {first_name Arthur} {street 1 Fern Way} {city Elwood City} {state PA} {age 8}]

Cursor类型也使用All()方法,该方法将游标中存储的所有文档同时反序列化到数组中。

bson包包括一系列与[]byte类型BSON编码数据一起工作的Marshal()Unmarshal()方法。

以下代码演示了如何使用bson包中的方法将BSON反序列化回用户定义的结构体

type Item struct {
Category string
Quantity int32
}
doc, err := bson.Marshal(bson.D{{"category", "plate"}, {"quantity", 6}})
var test Item
err = bson.Unmarshal(doc, &test)
fmt.Printf("Unmarshalled Struct:\n%+v\n", test)
Unmarshalled Struct:
{Category:plate Quantity:6}

注意

您可以使用Raw类型从BSON文档字节数组中检索元素,而无需将其反序列化到Go类型。此类型允许您在不反序列化整个BSON文档的情况下查找单个元素。

有关与Cursor类型一起使用的序列化和反序列化方法的更多信息,请参阅Cursor API文档

有关bson包中序列化和反序列化方法的更多信息,请参阅bson API文档

返回

企业身份验证