Docs 菜单
Docs 主页
/ / /
Go 驱动程序
/

使用 BSON

在本指南中,你可以了解 Go 驱动程序如何处理 BSON 和 Go 类型之间的转换。将 GO 类型转换为 BSON 的过程称为编组,反之称为解组

以下部分解释 Go 驱动程序如何表示 BSON 数据 以及您如何调整默认编组和解组行为。

MongoDB 采用名为 BSON 的二进制表示形式存储文档,可以轻松灵活地进行数据处理。

Go 驱动程序提供了四类主要驱动程序来处理 BSON 数据:

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

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

  • A:BSON 数组的有序表示形式

  • E:D 类型内部的单个元素

以下示例演示如何使用 bson.D 类型构造查询筛选器,匹配其中 quantity 字段值大于 100 的文档:

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

要学习;了解有关Go驾驶员如何处理BSON数据的更多信息,请参阅BSON包API文档。

在 Go 中,结构体是具有声明数据类型的数据字段的集合。您可以使用结构体标记修改结构体字段的默认编组和解组行为,结构体标记是附加到结构体字段的可选元数据片段。结构体标记最常见的用途是指定 BSON 文档中与结构体字段对应的字段名称。下表给出可以在 Go 驱动程序中使用的其他结构体标记:

结构标记
说明

omitempty

如果字段设置为与字段类型对应的零值,则不会对字段进行编组。如要全局防止驱动程序将设置为零值的字段进行编组,您可以设置 OmitEmpty BSON 选项。如要了解如何设置 OmitEmpty BSON 选项的更多信息,请参阅本页 BSON 选项部分中的示例。

minsize

如果该字段的类型为 int64uintuint32uint64,并且该字段的值适合采用有符号 int32 来表示,则该字段将被序列化为 BSON int32 而不是BSON int64。如果字段值不适合采用有符号 int32 来表示,则忽略此标签。

truncate

如果字段类型是非浮点数字类型, 则解组到该字段中的 BSON double 将在小数点处截断。

inline

如果字段类型是结构或映射字段,则字段在编组时将扁平化, 而在解组时将取消扁平化。

如果您不指定结构体标记,则 Go 驱动程序将使用以下规则编组结构体:

  1. 驱动程序仅编组和解组已导出的字段。

  2. 驱动程序使用相应结构体字段的小写字母生成 BSON 密钥。

  3. 此驱动程序会将嵌入的结构字段封送为子文档。每个键 均为该字段的小写类型表示法。

  4. 如果指针不为 nil,则驱动程序会将指针字段作为底层类型。 如果指针为 nil,则驱动程序将其编组为 BSON null 值。

  5. 解组时,Go 驱动程序会针对 interface{} 类型的字段遵循这些 D/M 类型映射。驱动程序将 BSON 文档解组为 D 类型,解组到 interface{} 字段中。

以下示例展示了 Go 驱动程序如何使用各种结构体标签对结构体编组:

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 数组

    • OmitEmpty 字段设置为 true,指示驱动程序全局省略编组 BSON 中的空值,而不是将空值设置为 null

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

  • 创建 Client 以应用指定的 BSON 封送和拆收行为

bsonOpts := &options.BSONOptions {
UseJSONStructTags: true,
NilSliceAsEmpty: true,
OmitEmpty: true,
}
clientOpts := options.Client().
ApplyURI("<connection string>").
SetBSONOptions(bsonOpts)
client, err := mongo.Connect(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 包包括一系列 Marshal()Unmarshal() 方法,这些方法可处理 []byte 类型的 BSON 编码数据。

以下代码演示如何使用 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 文档

后退

企业身份验证

在此页面上