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

使用 BSON

在此页面上

  • Overview
  • 数据类型
  • 结构体标记
  • 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
如果字段设置为与字段类型对应的零值,则不会对字段编组。
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 数组

  • 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 包包括一系列 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 文档

后退

企业身份验证