对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Docs 菜单

使用游标访问数据

在本指南中,您可以了解如何使用 Rust 驱动程序通过游标访问读取操作或聚合返回的数据。 游标是一种机制,可让您迭代多个文档,同时在给定时间仅在内存中保存其中的子集。

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

Cursor运行读操作或聚合后,返回的实例包含该操作的批处理结果。当您遍历游标时,服务器会返回更多单独的结果。 如果在到达一批处理结果的末尾后还有更多匹配文档,则Cursor实例将获取下一批处理文档,直到返回所有结果。

本指南包括以下部分:

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

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

  • 以数组形式检索文档描述了如何通过收集返回的游标结果,以单个大量形式访问权限所有结果

  • 检索原始文档批处理描述了如何使用原始批处理游标API进行零拷贝文档处理并直接访问权限BSON数据

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

  • 附加信息提供了本指南中提到的类型和方法的资源和 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()方法返回对游标中当前结果的引用,并将结果反序列化为与游标关联的类型。 除非指定类型,否则该方法将使用对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" }]

警告

避免超出应用程序内存限制

避免将大量结果转换为数组。 如果大量超过可用应用程序内存大小,应用应用程序可能会崩溃。 如果需要大型结果设立,请分别从游标中检索文档。 要学习;了解如何遍历游标,请参阅本指南的“单独检索文档”部分。

您可以对游标返回操作(例如 find())调用 batch() 方法,以返回 RawBatchCursor。这允许您迭代服务器返回的原始BSON文档批处理,而不是单个反序列化值。当您需要直接访问权限服务器响应批处理时,此模块提供了一种高性能的文档进程方法。对具有高吞吐量的性能敏感游标应用程序使用原始批处理模式。

要使用原始批处理游标API,请对游标返回操作调用 batch() 方法以返回 RawBatchCursor,而不是常规的 Cursor。然后,您可以遍历批处理并访问权限每个批处理中的单个文档。

以下示例展示了如何使用原始批处理游标来进程文档:

let mut cursor = my_coll.find(doc! { "color": "red" }).batch().await?;
while let Some(batch) = cursor.next().await {
let batch = batch?;
let doc_slices = batch.doc_slices()?;
let count = doc_slices.into_iter().count();
println!("Processing batch with {} documents", count);
for doc_result in batch.doc_slices()? {
let doc = doc_result?;
if let mongodb::bson::RawBsonRef::Document(raw_doc) = doc {
println!("Raw document size: {} bytes", raw_doc.as_bytes().len());
}
}
}
Processing batch with 4 documents
Raw document size: 58 bytes
Raw document size: 59 bytes
Raw document size: 58 bytes
Raw document size: 59 bytes

要学习;了解有关原始批处理游标API 的更多信息,请参阅API文档中的raw_batch_cursor页面。

要修改操作返回的游标,请将选项构建器方法链接到返回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 文档: