对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。
Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
MongoDB Branding Shape
Click here >
Docs 菜单

查找文档

在本指南中,您可以了解如何使用读取操作从 MongoDB collection中检索数据。读取操作是从服务器检索文档的命令。

有两种类型的读取操作:

  • 查找操作,允许您从collection中检索文档

  • 聚合操作,允许转换collection中的数据

本指南包括以下部分:

  • 示例的示例数据显示了读取操作示例使用的样本数据

  • 查找操作描述了如何使用驱动程序执行查找操作

  • 聚合操作描述了如何使用驱动程序执行聚合操作

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

本指南中的几个示例使用了以下示例文档。每个文档代表存储库存中的一个商品,并包含有关其分类和单价的信息:

let docs = vec![
Inventory {
item: "candle".to_string(),
category: "decor".to_string(),
unit_price: 2.89,
},
Inventory {
item: "blender".to_string(),
category: "kitchen".to_string(),
unit_price: 38.49,
},
Inventory {
item: "placemat".to_string(),
category: "kitchen".to_string(),
unit_price: 3.19,
},
Inventory {
item: "watering can".to_string(),
category: "garden".to_string(),
unit_price: 11.99,
},
];

要学习;了解如何将此数据插入到集合中,请参阅插入文档指南。

使用查找操作从 MongoDB 检索数据。 查找操作由find()find_one()方法组成。

要查找所有符合条件的文档,请使用find()方法。 此方法将查询筛选器作为参数。 查询筛选器由构成要匹配的文档条件的字段和值组成。

该方法返回一个Cursor类型,您可以遍历该类型以检索与过滤条件匹配的任何文档。

要查看使用此方法检索数据的示例,请参阅find() 示例。

要了解有关指定查询的更多信息,请参阅指定查询指南。

要查找第一个符合条件的文档,请使用find_one()方法。 此方法将查询筛选器作为参数。 查询筛选器由构成要匹配的文档条件的字段和值组成。

如果文档与筛选条件匹配,该方法将返回值为SomeResult<Option<T>>类型。 如果没有符合筛选条件的文档, find_one()将返回值为NoneResult<Option<T>>类型。

要查看使用此方法检索数据的示例,请参阅find_one()示例。

您可以通过将FindOptions选项构建器方法链接到find()来修改find()方法的行为,也可以通过将FindOneOptions选项构建器方法链接到find_one()来修改find_one()方法的行为。

下表描述了常用的FindOptionsFindOneOptions字段,您可以通过调用相应的构建器方法来设立这两个字段:

字段
说明

collation

对结果进行排序时使用的排序规则。要学习;了解有关排序规则的更多信息,请参阅排序规则指南。类型:

Collation
默认值:None

hint



用于操作的索引。要学习;了解有关索引的更多信息,请参阅服务器手册中的索引。类型:Hint
默认值:None

projection

返回结果时要使用的投影。要学习;了解有关投影的更多信息,请参阅《指定要返回的字段》指南。类型:

Document
默认值:None

read_concern

用于查找操作的读关注(read concern)。如果不设立此选项,该操作将继承为集合的读关注(read

concern)。要学习;了解有关读关注的更多信息,请参阅服务器手册中的读关注。类型:ReadConcern

skip

返回结果时要跳过的文档数。要详细学习;了解如何使用skip() 构建器方法,请参阅 Skip。类型:

u64
默认值:None

sort

返回结果时使用的排序。默认默认下,驾驶员按文档的自然顺序或按它们在数据库中的显示顺序返回文档。要学习;了解更多信息,请参阅服务器手册术语表中的自然顺序。要学习;了解有关如何使用 sort()

构建器方法的详情,请参阅排序。类型:Document
默认值:None

注意

设置选项

您可以通过将选项构建者方法直接链接到查找操作方法调用设立FindOptionsFindOneOptions 字段。如果使用的是早期版本的驱动程序,则必须通过将选项构建器方法链接到 builder() 方法来构造 FindOptionsFindOneOptions实例。然后,将选项实例作为参数传递给 find()find_one()

有关可以为每种类型指定的设置的完整列表,请参阅 FindOptionsFindOneOptions 的API文档。

以下部分包含使用find()find_one()方法检索与过滤条件匹配的样本文档的示例。

此示例将执行以下动作:

  • 调用find()方法

  • 将查询过滤传递给find() ,用于匹配unit_price值小于12.00category值不为"kitchen"的文档

  • sort()方法链接到find() ,以按unit_price降序对匹配的文档进行排序

let mut cursor = my_coll
.find(doc! { "$and": vec!
[
doc! { "unit_price": doc! { "$lt": 12.00 } },
doc! { "category": doc! { "$ne": "kitchen" } }
] })
.sort(doc! { "unit_price": -1 })
.await?;
while let Some(result) = cursor.try_next().await? {
println!("{:?}", result);
}
Inventory { item: "watering can", category: "garden", unit_price: 11.99 }
Inventory { item: "candle", category: "decor", unit_price: 2.89 }

此示例从 sample_restaurants数据库的 restaurants集合中检索与查询过滤匹配的文档。 find() 方法会返回 cuisine字段的值为 "French" 的所有文档。

您可以将每个检索到的文档建模为 Document 类型或自定义数据类型。 要指定哪种数据类型表示集合的数据,请将突出显示的行上的 <T> 类型参数替换为以下值之一:

  • <Document>:检索集合文档并将其打印为BSON文档

  • <Restaurant>:检索集合文档并将其打印为 Restaurant 结构的实例,该结构在代码顶部定义

选择AsynchronousSynchronous标签页,查看每个运行时的相应代码:

use mongodb::{
bson::doc,
Client,
Collection
};
use futures::TryStreamExt;
use serde::{ Deserialize, Serialize };
#[derive(Serialize, Deserialize, Debug)]
struct Restaurant {
name: String,
cuisine: String,
}
#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
let uri = "<connection string>";
let client = Client::with_uri_str(uri).await?;
// Replace <T> with the <Document> or <Restaurant> type parameter
let my_coll: Collection<T> = client
.database("sample_restaurants")
.collection("restaurants");
let mut cursor = my_coll.find(
doc! { "cuisine": "French" }
).await?;
while let Some(doc) = cursor.try_next().await? {
println!("{:#?}", doc);
}
Ok(())
}
use mongodb::{
bson::doc,
sync::{Client, Collection}
};
use serde::{ Deserialize, Serialize };
#[derive(Serialize, Deserialize, Debug)]
struct Restaurant {
name: String,
cuisine: String,
}
fn main() -> mongodb::error::Result<()> {
let uri = "<connection string>";
let client = Client::with_uri_str(uri)?;
// Replace <T> with the <Document> or <Restaurant> type parameter
let my_coll: Collection<T> = client
.database("sample_restaurants")
.collection("restaurants");
let mut cursor = my_coll.find(
doc! { "cuisine": "French" }
).run()?;
for result in cursor {
println!("{:#?}", result?);
}
Ok(())
}

选择 BSON Document ResultsRestaurant Struct Results标签页,根据集合的类型参数查看相应的代码输出:

...
Some(
Document({
"_id": ObjectId(
"...",
),
...
"name": String(
"Cafe Un Deux Trois",
),
...
}),
),
Some(
Document({
"_id": ObjectId(
"...",
),
...
"name": String(
"Calliope",
),
...
}),
)
...
...
Restaurant {
name: "Cafe Un Deux Trois",
cuisine: "French",
}
Restaurant {
name: "Calliope",
cuisine: "French",
}
...

您可以将查询筛选条件存储在JSON文件中,并在运行时加载。这种方法允许您在Rust应用程序和外部工具(例如MongoDB Shell (mongosh))之间股票查询定义。

提示

Serde JSON依赖项

在从文件加载查询之前,请从项目根目录运行以下命令以添加 serde_json 依赖项:

cargo add serde_json

首先,创建一个包含查询筛选条件的JSON文件。以下示例query.json文件包含一个比较查询筛选条件,用于匹配 category字段值为 "kitchen" 的文档:

query.json
{ "category": "kitchen" }

要将此文件加载到Rust应用程序中,请使用 std::fs::read_to_string() 方法读取该文件。然后,调用 serde_json::from_str() 将JSON字符串解析为 Document实例。由于 Document 实现了 serde::Deserialize 特征,因此您可以直接从JSON字符串对其进行反序列化。

以下示例从 query.json文件读取查询筛选条件并将其传递给 find() 方法:

let json = std::fs::read_to_string("query.json")
.expect("failed to read query.json");
let filter: Document = serde_json::from_str(&json)
.expect("query.json contains invalid JSON");
let mut cursor = my_coll.find(filter).await?;
while let Some(doc) = cursor.try_next().await? {
println!("{:?}", doc);
}
Inventory { item: "blender", category: "kitchen", unit_price: 38.49 }
Inventory { item: "placemat", category: "kitchen", unit_price: 3.19 }

此示例将执行以下动作:

  • 调用find_one()方法

  • 将查询过滤传递给find_one() ,用于匹配unit_price值小于或等于20.00的文档

  • skip()方法链接到find_one()以跳过前两个匹配的文档

let result = my_coll
.find_one(doc! { "unit_price": doc! { "$lte": 20.00 } })
.skip(2)
.await?;
println!("{:#?}", result);
Some(
Inventory {
item: "watering can",
category: "garden",
unit_price: 11.99,
},
)

此示例从 sample_restaurants数据库的 restaurants集合中检索与查询过滤匹配的文档。 find_one() 方法返回 name字段值为 "Tompkins Square Bagels" 的第一个文档。

您可以将检索到的文档建模为 Document 类型或自定义数据类型。 要指定哪种数据类型表示集合的数据,请将突出显示的行上的 <T> 类型参数替换为以下值之一:

  • <Document>:检索集合文档并将其打印为BSON文档

  • <Restaurant>:检索集合文档并将其打印为 Restaurant 结构的实例,该结构在代码顶部定义

选择AsynchronousSynchronous标签页,查看每个运行时的相应代码:

use mongodb::{
bson::doc,
Client,
Collection
};
use serde::{ Deserialize, Serialize };
#[derive(Serialize, Deserialize, Debug)]
struct Restaurant {
name: String,
cuisine: String,
}
#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
let uri = "<connection string>";
let client = Client::with_uri_str(uri).await?;
// Replace <T> with the <Document> or <Restaurant> type parameter
let my_coll: Collection<T> = client
.database("sample_restaurants")
.collection("restaurants");
let result = my_coll.find_one(
doc! { "name": "Tompkins Square Bagels" }
).await?;
println!("{:#?}", result);
Ok(())
}
use mongodb::{
bson::doc,
sync::{Client, Collection}
};
use serde::{ Deserialize, Serialize };
#[derive(Serialize, Deserialize, Debug)]
struct Restaurant {
name: String,
cuisine: String,
}
fn main() -> mongodb::error::Result<()> {
let uri = "<connection string>";
let client = Client::with_uri_str(uri)?;
// Replace <T> with the <Document> or <Restaurant> type parameter
let my_coll: Collection<T> = client
.database("sample_restaurants")
.collection("restaurants");
let result = my_coll.find_one(
doc! { "name": "Tompkins Square Bagels" }
).run()?;
println!("{:#?}", result);
Ok(())
}

选择 BSON Document ResultRestaurant Struct Result标签页,根据集合的类型参数查看相应的代码输出:

Some(
Document({
"_id": ObjectId(
"...",
),
...
"name": String(
"Tompkins Square Bagels",
),
...
}),
)
Some(
Restaurant {
name: "Tompkins Square Bagels",
cuisine: "American",
},
)

使用聚合操作从collection中检索和转换数据。您可以使用aggregate()方法执行聚合操作。

aggregate()方法将聚合管道作为参数。 聚合管道包括一个或多个指定如何转换数据的阶段。 阶段包括聚合操作符(以$为前缀)以及该操作符所需的任何参数。

要了解有关聚合的更多信息并查看聚合示例,请参阅聚合指南。

该方法以Cursor类型返回结果文档。 如果聚合管道不包含$match阶段,则管道会处理集合中的所有文档。

您可以通过将AggregateOptions选项构建器方法链接到aggregate()来修改aggregate()方法的行为。

下表描述了常用的AggregateOptions字段,您可以通过调用相应的构建器方法来设立这些字段:

字段
说明

allow_disk_use

允许写入临时文件。如果为true ,聚合阶段可以将数据写入_tmp 目录中的dbPath 子目录。类型:

bool
默认值:false

batch_size

指定服务器在每个游标批处理返回的最大文档数。此选项设置游标在内存中保留的文档数,而不是游标返回的文档数。类型:

默认值:最初有u32
101个文档,后续批次的最大16 MB

collation

对结果进行排序时使用的排序规则。要学习;了解有关排序规则的更多信息,请参阅排序规则指南。类型:

Collation
默认值:None

hint



用于操作的索引。要学习;了解有关索引的更多信息,请参阅服务器手册中的索引。类型:Hint
默认值:None

read_concern

用于查找操作的读关注(read concern)。如果不设立此选项,该操作将继承为集合的读关注(read

concern)。要学习;了解有关读关注的更多信息,请参阅服务器手册中的读关注。类型:ReadConcern

write_concern

该操作的写关注(write concern)。如果不设立此选项,该操作将继承为集合的写关注(write

concern)。要学习;了解有关写入关注的更多信息,请参阅服务器手册中的写关注。类型:WriteConcern

有关设置的完整列表,请参阅 AggregateOptions 的API文档。

此示例演示如何使用包含以下阶段的管道调用aggregate()方法:

  • $group 阶段,用于计算 category字段的每个值的 unit_price字段的平均值

  • $sort 阶段按 avg_price 升序对结果进行排序

let pipeline = vec![
doc! { "$group": doc! { "_id" : doc! {"category": "$category"} ,
"avg_price" : doc! { "$avg" : "$unit_price" } } },
doc! { "$sort": { "_id.avg_price" : 1 } },
];
let mut cursor = my_coll.aggregate(pipeline).await?;
while let Some(result) = cursor.try_next().await? {
println!("{:?}", result);
}
Document({"_id": Document({"category": String("decor")}), "avg_price": Double(2.890000104904175)})
Document({"_id": Document({"category": String("kitchen")}), "avg_price": Double(20.840000867843628)})
Document({"_id": Document({"category": String("garden")}), "avg_price": Double(11.989999771118164)})

有关查找操作的可运行示例,请参阅以下用法示例:

要了解有关本指南中操作的更多信息,请参阅以下文档:

要进一步了解本指南所提及的方法和类型,请参阅以下 API 文档: