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

常见问题解答

本页面

  • 为什么我在连接 MongoDB 时会收到错误?
  • Go 驱动程序中的连接池是如何工作的?
  • 我如何修复“WriteNull 只能在位于 Element 或 Value 时写入,但现在位于 TopLevel”错误?
  • 我如何将 BSON 文档转换为 JSON?

本页面包含常见问题及其答案。

提示

如果您在本页找不到问题的答案,请参阅问题与帮助 页面以获取下一步操作和更多资源。

如果您在连接到 MongoDB 部署时遇到问题,请参阅 连接故障排除指南 以获取可能的解决方案。

每个客户端 实例为您的 MongoDB 布局中的每个服务器内置一个连接池。连接池按需打开套接字以支持并发 MongoDB 操作,或者goroutines,在您的应用程序中。

每个连接池的最大大小由 maxPoolSize 选项设置,默认为 100。如果连接到服务器的使用中连接数达到 maxPoolSize 的值,则下一个对该服务器的请求将等待直到有连接可用。

客户端实例在每个MongoDB拓扑中的服务器上打开两个额外的套接字,用于监控服务器状态。

例如,连接到3节点副本集的客户端打开6个监控套接字。它还打开必要的套接字以支持每个服务器上应用程序的并发操作,最多达到maxPoolSize的值。如果maxPoolSize是100,并且应用程序仅使用主节点(默认),则仅主节点连接池会增长,总连接数最多为106。如果应用程序使用读取偏好来查询从节点,它们的池也会增长,总连接数最多为306

此外,连接池受到速率限制,这样每个连接池在任何时候最多只能并行创建maxConnecting个连接。在以下情况下,任何额外的goroutine停止等待:

  • 其中一个现有的goroutine完成创建连接,或者现有的连接被归还到池中。

  • 由于创建连接的速率限制,驱动程序重用现有连接的能力得到提高。

您可以通过使用minPoolSize选项来设置每个服务器要并发连接的最小数量,该选项默认为0。设置minPoolSize后,连接池以这个数量的套接字初始化。如果由于任何网络错误而导致套接字关闭,导致(使用中和空闲的)套接字总数低于最小值,则打开更多的套接字,直到达到最小值。

您可以通过使用maxIdleTimeMS选项来设置连接在池中保持空闲的最大毫秒数,以便被移除并替换,该选项默认为None(无限制)。

以下Client的默认配置适用于大多数应用程序

client := mongo.Connect(context.TODO(), "<connection string>")

为每个进程创建一次客户端,并重用它进行所有操作。为每个请求创建一个新的客户端是一个常见的错误,这样做非常低效。

为了在一个进程中支持大量并发MongoDB操作,您可以增加maxPoolSize。一旦池达到其最大大小,额外的操作将等待套接字可用。

驱动程序不限制可以等待套接字可用的操作数,限制池的大小以在负载峰值期间限制排队是应用程序的责任。除非您定义了waitQueueTimeoutMS选项,否则操作可以等待任意长度的时间。

等待时间超过由waitQueueTimeoutMS定义的时间长度的操作将引发连接错误。如果您更重视在负载峰值期间限制操作持续时间,而不是完成每个操作,请使用此选项。

当任何goroutine调用Client.Disconnect()时,驱动程序将关闭所有空闲套接字,并在它们返回池中时关闭所有正在使用的套接字。

bson.Marshal() 方法需要一个可以解码为BSON文档的参数,例如 bson.D 类型。当您将除BSON文档之外的内容传递给 bson.Marshal() 时,会引发此错误。

当您将 null 传递给 bson.Marshal() 时,会发生 WriteNull 错误。可能发生类似错误的情况包括以下几种

  • 您将字符串传递给 bson.Marshal(),导致发生 WriteString 错误。

  • 您将布尔值传递给 bson.Marshal(),导致发生 WriteBoolean 错误。

  • 您将整数传递给 bson.Marshal(),导致发生 WriteInt32 错误。

您在执行使用内部 bson.Marshal() 方法的CRUD操作或直接调用 bson.Marshal() 来编码数据时可能会遇到此错误。

以下代码会产生 WriteNull 错误,因为驱动程序无法在 FindOneAndUpdate() 操作期间将 sortOrdernull 值编码为BSON。

var sortOrder bson.D
opts := options.FindOneAndUpdate().SetSort(sortOrder)
updateDocument := bson.D{{"$inc", bson.D{{"counter", 1}}}}
result := coll.FindOneAndUpdate(context.TODO(), bson.D{}, updateDocument, opts)
if err := result.Err(); err != nil {
panic(err)
}

以下代码显示了如何正确初始化 sortOrder 变量为 bson.D 类型,以便驱动程序将其转换为BSON。

sortOrder := bson.D{}

驱动程序提供了各种marshaler方法,可以将BSON文档转换为JSON,例如 MarshalExtJSON() 方法。要查看JSON编码的可读形式,必须使用unmarshaler方法或字符串类型转换来解析JSON字节格式。

以下代码使用 MarshalExtJSON() 方法将 BSON 文档转换为 JSON,然后使用字符串类型转换解析并打印 JSON 字节数组。

bsonDocument := bson.D{{"hello", "world"}}
jsonBytes, err := bson.MarshalExtJSON(bsonDocument, true, false)
if err != nil {
panic(err)
}
fmt.Println(string(jsonBytes))
{"hello":"world"}

要了解更多关于 BSON 和 Go 类型之间转换的信息,请参阅 使用 BSON 指南。

返回

地理空间数据