文档菜单
文档首页
/ / /
Rust 驱动
/ / /

使用游标访问数据

本页内容

  • 概述
  • 示例数据的样本
  • 逐个检索文档
  • 内置模式
  • 流实现模式
  • 按数组形式检索文档
  • 指定游标行为
  • 更多信息
  • API 文档

在本指南中,您可以学习如何使用Rust驱动程序,通过使用游标来访问读取操作或聚合操作返回的数据。游标是一种机制,允许您在给定时间内只将部分文档保留在内存中,同时遍历多个文档。

驱动程序提供了Cursor类型来从游标中检索文档。例如,当您运行可以返回多个文档的查找操作时,驱动程序返回一个Cursor实例,您可以通过该实例访问匹配的文档。

运行读取操作或聚合操作后,返回的Cursor实例包含操作的第一批结果。随着您遍历游标,服务器返回更多的单个结果。如果在达到一批结果结束时还有更多匹配的文档,则Cursor实例将检索下一批文档,直到所有结果返回。

本指南包括以下部分

  • 示例数据的样本展示了游标示例所使用的样本数据

  • 逐个检索文档描述了如何使用迭代或流逐个访问结果

  • 按数组形式检索文档描述了如何通过收集返回的游标结果将所有结果作为单个数组访问

  • 指定游标行为描述了如何配置方法返回的游标

  • 更多信息提供了到资源链接和本指南中提到的类型和方法的API文档

本指南中的示例使用以下存储在结构体中的数据

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实例返回的文档

  • 内置模式:移动游标,然后检索和反序列化当前文档

  • 流实现模式:遍历游标,并调用Stream提供的方法来处理单个或多个文档

以下章节将更详细地描述这些访问模式和相应的方法。

您可以使用驱动程序的内置访问模式逐个检索和处理文档。

Cursor类型包括advance()deserialize_current()方法,用于遍历游标并逐个访问文档。

advance() 方法将光标向前移动,并在本地缓冲区耗尽时向数据库发送请求以获取更多结果,这发生在光标到达结果批次末尾时。每次光标到达结果批次末尾时,都会请求下一批次。当光标没有更多匹配的文档返回并且不再可用时,光标就会耗尽。如果成功返回新结果,则 advance() 方法返回一个 true 结果,如果光标被关闭,则返回一个 false 结果。

deserialize_current() 方法返回光标中当前结果的引用,并将结果反序列化为与光标关联的类型。除非您指定类型,否则该方法将使用与您的集合参数化相同的类型。

重要

只有在 advance() 方法返回一个 true 结果的情况下,才能调用 deserialize_current() 方法。如果您在没有 true 结果或未先调用 advance() 的情况下对光标调用 deserialize_current(),则驱动程序将生成错误。

以下示例展示了如何实现此访问模式以遍历对 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>> 类型

重要

Stream 模式方法所需导入

要使用 next() 方法,您必须导入 StreamExt 特性。要使用 try_next() 方法,您必须导入 TryStreamExt 特性。

以下示例展示了如何实现这两个流方法以遍历对 fruits 集合的查找操作的结果。

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
指定服务器每次游标批处理返回的最大文档数。此选项设置游标在内存中保留的文档数,而不是游标返回的文档数。

类型: u32
默认值: 初始时为 101 个文档,后续批次最大为 16 MB
cursor_type
指定要返回的游标类型。您可以设置此选项以生成可尾随的游标。有关可尾随游标的更多信息,请参阅服务器手册中的 可尾随游标

类型: CursorType
默认值: CursorType::NonTailable
no_cursor_timeout
指定服务器是否在一段时间的不活动后关闭游标。

重要:由于 Cursor 类型实现了 Drop 特性,当游标超出作用域时,服务器会关闭游标。服务器运行异步的 killCursors 命令来关闭游标。有关更多信息,请参阅服务器手册中的 killCursors
类型: bool
默认值: false

以下代码显示了如何通过将选项构建器方法链接到 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 文档

返回

指定查询