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

批量操作

本页内容

  • 概述
  • 示例数据
  • 批量操作类型
  • 插入
  • 替换
  • 更新
  • 删除
  • 返回类型
  • 修改行为
  • 示例
  • 写入到混合命名空间
  • 附加信息

在这份指南中,您可以学习如何使用Rust驱动程序执行批量操作

批量操作针对一个或多个命名空间执行多个写入操作。命名空间是数据库名和集合名的组合,格式为<database>.<collection>。由于您在Client实例上执行批量操作,因此您可以对客户端访问的集群中的任何命名空间执行批量操作。

您可以通过执行批量操作来减少对服务器的调用次数。而不是为每个操作发送请求,批量操作在一个动作中执行多个操作。

本指南包括以下部分

  • 示例数据展示了批量操作示例所使用的示例数据

  • 批量操作类型描述了如何使用WriteModel类型执行批量插入、替换、更新和删除操作

  • 返回类型描述了bulk_write()方法的返回值以及如何访问有关批量操作的信息

  • 修改行为描述了如何修改bulk_write()方法的默认行为

  • 写入混合命名空间描述了如何在单个方法调用中执行多个命名空间的批量操作

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

重要

要执行批量写入操作,请确保您的应用程序满足以下要求

  • 您连接到MongoDB Server版本8.0或更高版本。

  • 您正在使用Rust驱动程序版本3.0或更高版本。

本指南中的示例使用以下示例文档,这些文档存储在数据库 db 中的 mushrooms 集合中

let docs = vec![
doc! {"name" : "portobello", "color" : "brown", "edible" : true },
doc! {"name" : "chanterelle", "color" : "yellow", "edible" : true },
doc! {"name" : "oyster", "color" : "white", "edible" : true },
doc! {"name" : "fly agaric", "color" : "red", "edible" : false },
];

您还可以使用自定义结构类型来表示您的示例数据。有关使用 Mushroom 结构体来建模相同数据的批量操作示例,请参阅本页上的 插入结构体示例

要执行批量写入操作,请将 WriteModel 枚举实例数组传递给 bulk_write() 方法。

在本节中,您可以通过定义相应的 WriteModel 类型来学习如何执行以下批量写入操作

提示

您还可以在单个 bulk_write() 方法调用中执行多种类型的写入操作。要查看示例,该示例将 UpdateOneModelInsertOneModel 传递给同一个 bulk_write() 调用,请参阅本指南中的 修改行为示例

要执行批量插入操作,为要插入的每个文档创建一个 InsertOneModel 实例。然后,将模型列表传递给 bulk_write() 方法。

以下表格描述了您可以通过调用相应构建方法设置的 InsertOneModel 字段

字段
描述
namespace
执行插入操作的命名空间。
类型: Namespace
document
要插入的文档。
类型: Document

此示例执行以下操作

  • 在数组中指定了两个 InsertOneModel 实例。每个 InsertOneModel 代表要插入到 db.mushrooms 命名空间中的文档。

  • 将模型数组传递给 bulk_write() 方法。

  • 打印插入的文档数量。

let mushrooms: Collection<Document> = client.database("db").collection("mushrooms");
let models = vec![
InsertOneModel::builder()
.namespace(mushrooms.namespace())
.document(doc! {
"name": "lion's mane",
"color": "white",
"edible": true
})
.build(),
InsertOneModel::builder()
.namespace(mushrooms.namespace())
.document(doc! {
"name": "angel wing",
"color": "white",
"edible": false
})
.build(),
];
let result = client.bulk_write(models).await?;
println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2

您还可以使用结构体来建模文档,并将批量插入结构体实例到 db.mushrooms 命名空间。

此示例执行的操作与前面的 插入文档示例 相同,但插入以下 Mushroom 结构体类型的实例

#[derive(Serialize)]
struct Mushroom {
name: String,
color: String,
edible: bool,
}

以下代码使用insert_one_model()方法从每个Mushroom实例构建一个InsertOneModel,然后在批量操作中插入这两个模型。

let mushrooms: Collection<Mushroom> = client.database("db").collection("mushrooms");
let lions_mane = Mushroom {
name: "lion's mane".to_string(),
color: "white".to_string(),
edible: true,
};
let angel_wing = Mushroom {
name: "angel wing".to_string(),
color: "white".to_string(),
edible: false,
};
let lions_mane_model = mushrooms.insert_one_model(lions_mane)?;
let angel_wing_model = mushrooms.insert_one_model(angel_wing)?;
let result = client.bulk_write([lions_mane_model, angel_wing_model]).await?;
println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2

提示

要了解更多关于Rust驱动中的自定义结构类型和序列化的信息,请参阅数据建模和序列化指南.

要执行批量替换操作,为要替换的每个文档创建一个ReplaceOneModel实例。然后,将模型列表传递给bulk_write()方法。

以下表格描述了您可以设置其对应构建器方法的ReplaceOneModel字段

字段
描述
namespace
执行操作的命名空间。
类型: Namespace
filter
匹配要替换的文档的过滤器。
类型: Document
replacement
替换文档。
类型: Document
collation
(可选) 用于排序结果的排序规则。要了解更多关于排序规则的信息,请参阅排序规则指南。
类型: Document
hint
(可选) 用于操作的索引。要了解更多关于索引的信息,请参阅索引指南。
类型: Bson
upsert
(可选) 如果没有文档匹配过滤器,是否创建新文档。
默认情况下,此字段设置为false
类型: bool

此示例执行以下操作

  • 在数组中指定两个ReplaceOneModel实例。这些ReplaceOneModel实例包含替换在db.mushrooms命名空间中表示蘑菇的文档的指令。

  • 将模型数组传递给 bulk_write() 方法。

  • 打印修改的文档数。

let mushrooms: Collection<Document> = client.database("db").collection("mushrooms");
let models = vec![
ReplaceOneModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "name": "portobello" })
.replacement(doc! {
"name": "cremini",
"color": "brown",
"edible": true
})
.build(),
ReplaceOneModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "name": "oyster" })
.replacement(doc! {
"name": "golden oyster",
"color": "yellow",
"edible": true
})
.upsert(true)
.build(),
];
let result = client.bulk_write(models).await?;
println!("Modified documents: {}", result.modified_count);
Modified documents: 2

要执行批量更新操作,为每个要进行的更新创建一个UpdateOneModelUpdateManyModel实例。然后,将模型列表传递给bulk_write()方法。一个UpdateOneModel只更新匹配过滤器的一个文档,而一个UpdateManyModel则更新所有匹配过滤器的文档。

下表描述了您可以通过调用其相应构建方法设置的UpdateOneModelUpdateManyModel字段

字段
描述
namespace
执行操作的命名空间。
类型: Namespace
filter
匹配您想要更新的一个或多个文档的过滤器。当在UpdateOneModel中指定时,只有第一个匹配的文档将被更新。当在UpdateManyModel中指定时,所有匹配的文档都将被更新。
类型: Document
更新
要执行的操作。
类型: UpdateModifications
array_filters
(可选) 一组过滤器,指定在更新数组值字段时应用更新的数组元素。
类型: Array
collation
(可选) 用于排序结果的排序规则。要了解更多关于排序规则的信息,请参阅排序规则指南。
类型: Document
hint
(可选) 用于操作的索引。要了解更多关于索引的信息,请参阅索引指南。
类型: Bson
upsert
(可选) 如果没有文档匹配过滤器,是否创建新文档。默认情况下,此字段设置为false
类型: bool

此示例执行以下操作

  • 指定一个数组中的UpdateOneModelUpdateManyModel实例。这些模型包含更新表示db.mushrooms命名空间中的蘑菇文档的指令。

  • 将模型数组传递给 bulk_write() 方法。

  • 打印修改的文档数。

let mushrooms: Collection<Document> = client.database("db").collection("mushrooms");
let models = vec![
WriteModel::UpdateOne(
UpdateOneModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "name": "fly agaric" })
.update(doc! { "$set": { "name": "fly amanita" } })
.upsert(true)
.build(),
),
WriteModel::UpdateMany(
UpdateManyModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "color": "yellow" })
.update(doc! { "$set": { "color": "yellow/orange" } })
.build(),
),
];
let result = client.bulk_write(models).await?;
println!("Modified documents: {}", result.modified_count);
Modified documents: 2

要执行批量删除操作,为每个删除操作创建一个 DeleteOneModelDeleteManyModel 实例。然后,将模型列表传递给 bulk_write() 方法。一个 DeleteOneModel 仅删除匹配过滤器的单个文档,而一个 DeleteManyModel 删除所有匹配过滤器的文档。

以下表格描述了您可以调用其相应构建器方法设置的 DeleteOneModelDeleteManyModel 字段

字段
描述
namespace
执行操作的命名空间。
类型: Namespace
filter
匹配您想要删除的一个或多个文档的过滤器。当在 DeleteOneModel 中指定时,仅删除第一个匹配的文档。当在 DeleteManyModel 中指定时,将删除所有匹配的文档。
类型: Document
collation
(可选) 用于排序结果的排序规则。要了解更多关于排序规则的信息,请参阅排序规则指南。
类型: Document
hint
(可选) 用于操作的索引。要了解更多关于索引的信息,请参阅索引指南。
类型: Bson

此示例执行以下操作

  • 指定一个数组中的 DeleteOneModelDeleteManyModel 实例。这些模型包含在 db.mushrooms 命名空间中删除蘑菇文档的指令。

  • 将模型数组传递给 bulk_write() 方法。

  • 打印删除文档的数量。

let mushrooms: Collection<Document> = client.database("db").collection("mushrooms");
let models = vec![
WriteModel::DeleteOne(
DeleteOneModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "color": "red" })
.build(),
),
WriteModel::DeleteMany(
DeleteManyModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "edible": true })
.build(),
),
];
let result = client.bulk_write(models).await?;
println!("Deleted documents: {}", result.deleted_count);
Deleted documents: 4

bulk_write() 方法返回一个 SummaryBulkWriteResult 结构实例,您可以从该实例中获取有关批量操作的信息。

SummaryBulkWriteResult 类型有以下字段

  • inserted_count:插入的文档数量

  • matched_count:匹配的文档数量

  • modified_count:更新文档的数量

  • upserted_count:插入或更新文档的数量

  • deleted_count:删除文档的数量

您还可以使用 verbose_results() 方法查看每个操作的相关详细信息。该方法返回一个 VerboseBulkWriteResult 结构体实例,该实例具有以下字段

  • delete_results:每个成功删除操作的结果

  • insert_results:每个成功插入操作的结果

  • update_results:每个成功更新操作的结果

  • summary:每种操作类型的结果摘要

以下示例将 verbose_results() 方法链接到 bulk_write() 方法,并打印更新和删除操作的结果

let models = vec![
WriteModel::DeleteOne(
DeleteOneModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "name": "oyster" })
.build(),
),
WriteModel::UpdateOne(
UpdateOneModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "name": "chanterelle" })
.update(doc! { "$set": { "season": ["July", "August", "September"] } })
.build(),
),
];
let result = client.bulk_write(models).verbose_results().await?;
println!(
"Update results: {:?}\nDelete results: {:?}\n",
result.update_results, result.delete_results
);
Update results: {1: UpdateResult { matched_count: 1, modified_count: 1, upserted_id: None }}
Delete results: {0: DeleteResult { deleted_count: 1 }}

您可以通过设置 BulkWriteOptions 字段值来修改 bulk_write() 方法的行为。要将这些结构体字段设置,请将相应的方法链接到 bulk_write() 方法。

BulkWriteOptions 结构体包含以下字段

字段
描述
默认值
ordered
操作是否按指定顺序运行。
设置为 true 时,一个失败的操作会阻止后续操作运行。
设置为 false 时,如果其中一个操作失败,服务器将继续尝试写入操作。
类型: bool
true
bypass_document_validation
是否绕过文档级验证。
类型: bool
false
comment
一个任意注释,有助于通过数据库分析器、当前操作和日志追踪操作。
类型: Bson
None
let_vars
一个映射,包含要应用于批量写入中所有操作的参数名称和值。值必须是常量或闭包表达式,不引用文档字段。
类型: Document
None
write_concern
用于此批量操作的写入关注点。
类型: WriteConcern
继承命名空间的写入关注点

本示例尝试对mushrooms集合执行更新和插入操作。以下代码通过将ordered()方法链接到bulk_write()方法,将ordered字段设置为false

let mushrooms: Collection<Document> = client.database("db").collection("mushrooms");
let models = vec![
WriteModel::UpdateOne(UpdateOneModel::builder()
.namespace(mushrooms.namespace())
.filter(doc! { "name": "portobello" })
.update(doc! { "$set": { "_id": 123 } })
.upsert(true)
.build()),
WriteModel::InsertOne(InsertOneModel::builder()
.namespace(mushrooms.namespace())
.document(doc! {
"name": "reishi",
"color": "red/brown",
"edible": true
})
.build()),
];
let result = client.bulk_write(models).ordered(false).await?;
println!(
"Inserted documents: {}\nDeleted documents: {}",
result.inserted_count, result.deleted_count
);
Error: Error { kind: BulkWrite(BulkWriteError { write_concern_errors: [], write_errors:
{0: WriteError { code: 66, code_name: None, message: "Plan executor error during update ::
caused by :: Performing an update on the path '_id' would modify the immutable field '_id'",
details: None }}, partial_result: Some(Summary(SummaryBulkWriteResult { inserted_count: 1,
matched_count: 0, modified_count: 0, upserted_count: 0, deleted_count: 0 })) }),
labels: ... }

_id字段是不可变的,在更新操作中无法更改。由于UpdateOneModel包含更新此字段的指令,批量操作将返回一个BulkWriteError并仅执行插入操作。如果您将ordered字段设置为true,在更新操作失败后,驱动程序不会尝试任何后续操作,并且驱动程序不会插入任何文档。

页面上的前述示例对db.mushrooms命名空间执行批量操作。但是,您可以在单个方法调用中执行多个命名空间的批量写入。

以下示例向ingredients.sweet命名空间插入一个文档,并向meals.dessert命名空间插入一个文档。

let sweet: Collection<Document> = client
.database("ingredients")
.collection("sweet");
let dessert: Collection<Document> = client
.database("meals")
.collection("dessert");
let models = vec![
InsertOneModel::builder()
.namespace(sweet.namespace())
.document(doc! { "name": "brown sugar", "price": 3.99 })
.build(),
InsertOneModel::builder()
.namespace(dessert.namespace())
.document(doc! { "name": "banana bread", "cook_time": 75 })
.build(),
];
let result = client.bulk_write(models).await?;
println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2

有关批量操作的更多信息,请参阅服务器手册中的批量写入操作

返回

删除