常见问题解答
本页面
本页面包含常见问题及其答案。
提示
如果您在本页找不到问题的答案,请参阅问题与帮助 页面以获取下一步操作和更多资源。
为什么我在连接到 MongoDB 时会收到错误?
如果您在连接到 MongoDB 部署时遇到问题,请参阅 连接故障排除指南 以获取可能的解决方案。
Go 驱动程序中的连接池是如何工作的?
每个客户端
实例为您的 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()
时,驱动程序将关闭所有空闲套接字,并在它们返回池中时关闭所有正在使用的套接字。
如何修复“WriteNull只能在Element或Value上写入,但现在在TopLevel上”的错误?
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()
操作期间将 sortOrder
的 null
值编码为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{}
如何将BSON文档转换为JSON?
驱动程序提供了各种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 指南。