使用游标访问数据
Overview
在本指南中,您可以了解如何使用 Rust 驱动程序通过游标访问读取操作或聚合返回的数据。 游标是一种机制,可让您迭代多个文档,同时在给定时间仅在内存中保存其中的子集。
驱动程序提供 Cursor
类型以从游标检索文档。 例如,当您运行可以返回多个文档的查找操作时,驱动程序会返回一个Cursor
实例,您可以从该实例访问匹配的文档。
Cursor
运行读操作或聚合后,返回的实例包含该操作的批处理结果。当您遍历游标时,服务器会返回更多单独的结果。 如果在到达一批处理结果的末尾后还有更多匹配文档,则Cursor
实例将获取下一批处理文档,直到返回所有结果。
本指南包括以下部分:
示例样本数据
本指南中的示例使用存储在结构体中的以下数据:
let docs = vec! [ Fruit { name: "strawberry".to_string(), color: "red".to_string() }, Fruit { name: "banana".to_string(), color: "yellow".to_string() }, Fruit { name: "pomegranate".to_string(), color: "red".to_string() }, Fruit { name: "pineapple".to_string(), color: "yellow".to_string() } ];
分别检索文档
该驱动程序提供以下访问模式来遍历Cursor
实例返回的文档:
以下部分将更详细地描述这些访问模式和相应的方法。
内置模式
您可以使用驱动程序的内置访问模式逐份检索和处理文档。
Cursor
类型包括advance()
和deserialize_current()
方法,用于遍历游标并分别访问文档。
advance()
方法会向前移动游标,并在本地缓冲区耗尽时(游标到达一批处理结果的末尾时会发生这种情况)向数据库发送请求以获取更多结果。每次游标到达批处理结果的末尾时,它都会请求下一批处理结果。当游标没有更多匹配文档可返回并且不再可用时,游标已耗尽。 如果成功返回新结果,则advance()
方法会返回true
结果;如果关闭游标,则返回false
结果。
deserialize_current()
方法返回对游标中当前结果的引用,并将结果反序列化为与游标关联的类型。 除非指定类型,否则该方法将使用对collection进行参数化时使用的同一类型。
重要
仅当advance()
方法返回true
结果时,才能调用deserialize_current()
方法。 如果您在游标上调用deserialize_current()
没有true
结果,或者没有调用之前调用的advance()
,则驱动程序会生成错误。
以下示例展示了如何实现此访问模式以遍历collection上查找操作的结果:fruits
let mut cursor = my_coll.find(doc! { "color": "red" }).await?; while cursor.advance().await? { println!("{:?}", cursor.deserialize_current()?); }
Fruit { name: "strawberry", color: "red" } Fruit { name: "pomegranate", color: "red" }
流实现模式
您可以以流的形式访问游标结果,以检索单个文档或一次收集多个文档。
Cursor
类型实现了Stream
特征,因此您可以将游标作为流进行迭代。 与内置模式相比,此模式可帮助您编写更简洁的代码,因为Stream
扩展特征StreamExt
提供了许多用于组合操作和整合代码的函数。
您可以通过以下方法来使用流模式:
next()
:将游标前进到下一个结果并返回Option<Result<T>>
类型try_next()
:将游标前进到下一个结果并返回Result<Option<T>>
类型
重要
流模式方法所需的导入
要使用next()
方法,您必须导入StreamExt
特征。 要使用try_next()
方法,您必须导入TryStreamExt
特征。
fruits
以下示例展示了如何实现两个流方法以遍历collection上的查找操作结果:
let mut cursor = my_coll.find(doc! { "color": "red" }).await?; println!("Output from next() iteration:"); while let Some(doc) = cursor.next().await { println!("{:?}", doc?); } println!(); let mut cursor = my_coll.find(doc! { "color": "yellow" }).await?; println!("Output from try_next() iteration:"); while let Some(doc) = cursor.try_next().await? { println!("{:?}", doc); }
Output from next() iteration: Fruit { name: "strawberry", color: "red" } Fruit { name: "pomegranate", color: "red" } Output from try_next() iteration: Fruit { name: "banana", color: "yellow" } Fruit { name: "pineapple", color: "yellow" }
以数组形式检索文档
由于Cursor
类型实现了Stream
特征,因此您可以将游标的结果收集到数组中。
您可以使用以下方法以数组形式检索文档:
collect()
:将游标的结果收集为Vec<Result<T>>
类型try_collect()
:将游标的结果收集为Result<Vec<T>>
类型
注意
要使用collect()
方法,您必须导入StreamExt
特征。 要使用try_collect()
方法,您必须导入TryStreamExt
特征。
let cursor = my_coll.find(doc! { "color": "red" }).await?; println!("Output from collect():"); let v: Vec<Result<Fruit>> = cursor.collect().await; println!("{:?}", v); println!(); let cursor = my_coll.find(doc! { "color": "yellow" }).await?; println!("Output from try_collect():"); let v: Vec<Fruit> = cursor.try_collect().await?; println!("{:?}", v);
Output from collect(): [Ok(Fruit { name: "strawberry", color: "red" }), Ok(Fruit { name: "pomegranate", color: "red" })] Output from try_collect(): [Fruit { name: "banana", color: "yellow" }, Fruit { name: "pineapple", color: "yellow" }]
警告
避免超出应用程序内存限制
避免将大量结果转换为数组。 如果大量超过可用应用程序内存大小,应用应用程序可能会崩溃。 如果需要大型结果设立,请分别从游标中检索文档。 要学习;了解如何遍历游标,请参阅本指南的“单独检索文档”部分。
指定游标行为
要修改操作返回的游标,请将选项构建器方法链接到返回Cursor
实例的方法。 示例,您可以将与游标相关的选项构建器方法链接到find()
方法。
注意
设置选项
您可以通过将选项构建器方法直接链接到find()
方法调用来设立FindOptions
字段。 如果使用的是早期版本的驾驶员,则必须通过将选项构建器方法链接到builder()
方法来构造FindOptions
实例。 然后,将FindOptions
实例作为参数传递给find()
。
下表描述了与游标相关的选项,您可以通过调用相应的构建器方法来设立这些选项:
设置 | 说明 |
---|---|
batch_size | Specifies the maximum number of documents the server returns per
cursor batch. This option sets the number of documents the cursor
keeps in memory rather than the number of documents the cursor
returns. Type: u32 Default: 101 documents initially, 16 MB maximum for
subsequent batches |
cursor_type | Specifies the type of cursor to return. You can set this option
to produce a tailable cursor. To learn more about tailable
cursors, see Tailable Cursors in the Server manual. Type: CursorType Default: CursorType::NonTailable |
no_cursor_timeout |
以下代码演示如何通过将选项构建器方法链接到find()
方法来指定游标相关设置:
let mut cursor = my_coll.find(doc! { "color": "red" }) .batch_size(5) .cursor_type(CursorType::Tailable) .no_cursor_timeout(true) .await?;
更多信息
要了解有关本指南中操作的更多信息,请参阅以下文档:
要了解有关 Rust 类型和 BSON 之间转换的更多信息,请参阅数据建模和序列化指南。
API 文档
要进一步了解本指南所提及的方法和类型,请参阅以下 API 文档:
next() 在
StreamExt
特征中try_next() 在
TryStreamExt
特征中collect() 在
StreamExt
特征中try_collect() 在
TryStreamExt
特征中