Overview
在本指南中,可以了解如何使用游标访问数据。
游标是一种机制,允许应用程序遍历数据库结果,同时在给定时间内只在内存中保留其中的一个子集。匹配多个文档的读取操作会使用游标分批返回这些文档,而不是一次性返回所有文档。
示例游标
读取操作(如 Find() 方法)会返回引用与该操作匹配的文档的 Cursor。要获取游标,请首先连接到部署并访问集合,如以下示例所示:
var uri string if uri = os.Getenv("MONGODB_URI"); uri == "" { log.Fatal("You must set your 'MONGODB_URI' environment variable. See\n\t https://www.mongodb.com/zh-cn/docs/drivers/go/current/usage-examples/") } client, err := mongo.Connect(options.Client().ApplyURI(uri)) if err != nil { panic(err) } defer func() { if err := client.Disconnect(context.TODO()); err != nil { panic(err) } }() coll := client.Database("db").Collection("sample_data")
本指南中的示例使用以下 MyStruct 结构作为集合中文档的模型:
type MyStruct struct { MyProperty string }
以下代码将示例文档插入集合:
docs := []any{ MyStruct{MyProperty: "Beach House"}, MyStruct{MyProperty: "Office"}, MyStruct{MyProperty: "Bungalow"}, } result, err := coll.InsertMany(context.TODO(), docs) if err != nil { panic(err) }
要获取游标,请在集合上调用 Find() 方法来运行查询并返回游标。以下示例将空过滤器传递给集合中的所有文档,并将结果游标分配给 cursor 变量:
cursor, err := coll.Find(context.TODO(), bson.D{}) if err != nil { panic(err) }
本指南的每个部分都使用此 cursor 变量。驱动程序将游标引用的文档解组合到 MyStruct 结构。
重要
游标并不具备 goroutine 安全性。请勿在多个 goroutine 中同时使用同一游标。
分别检索文档
要在阻止当前 goroutine 的同时从游标单独检索文档,请使用 Next() 方法。
如果满足所有以下条件,该方法返回一个文档:
当前已提供或稍后会提供文档。
驱动程序没有报告任何错误。
上下文未过期。
for cursor.Next(context.TODO()) { var result MyStruct if err := cursor.Decode(&result); err != nil { log.Fatal(err) } fmt.Printf("%+v\n", result) } if err := cursor.Err(); err != nil { log.Fatal(err) }
可追加游标
要在不阻塞当前 goroutine 的情况下尝试检索文档,请使用 TryNext() 方法。在迭代可追加游标时使用此方法。
如果满足所有以下条件,该方法返回一个文档:
当前有文档可供使用。
驱动程序没有报告任何错误。
上下文未过期。
for { if cursor.TryNext(context.TODO()) { var result MyStruct if err := cursor.Decode(&result); err != nil { log.Fatal(err) } fmt.Printf("%+v\n", result) continue } if err := cursor.Err(); err != nil { log.Fatal(err) } if cursor.ID() == 0 { break } }
检索所有文档
要使用所有查询结果填充切片,请使用 All() 方法:
var results []MyStruct if err := cursor.All(context.TODO(), &results); err != nil { panic(err) } for _, result := range results { fmt.Printf("%+v\n", result) }
关闭游标
当应用程序不再需要游标时,请使用 Close() 方法关闭游标。此方法能够释放游标在客户端应用程序和 MongoDB 服务器中消耗的资源。
defer cursor.Close(context.TODO())
注意
当使用 Next() 或 TryNext() 方法 单独检索文档时,请始终关闭游标以释放其占用的资源。
更多信息
要了解有关本指南中讨论的操作的更多信息,请参阅以下指南:
API 文档
如需进一步了解游标以及如何访问游标元素,请参阅以下 API 文档: