批量操作
概述
在这份指南中,您可以学习如何使用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()
方法调用中执行多种类型的写入操作。要查看示例,该示例将 UpdateOneModel
和 InsertOneModel
传递给同一个 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
结构体类型的实例
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
更新
要执行批量更新操作,为每个要进行的更新创建一个UpdateOneModel
或UpdateManyModel
实例。然后,将模型列表传递给bulk_write()
方法。一个UpdateOneModel
只更新匹配过滤器的一个文档,而一个UpdateManyModel
则更新所有匹配过滤器的文档。
下表描述了您可以通过调用其相应构建方法设置的UpdateOneModel
和UpdateManyModel
字段
字段 | 描述 |
---|---|
namespace | 执行操作的命名空间。 类型: Namespace |
filter | 匹配您想要更新的一个或多个文档的过滤器。当在 UpdateOneModel 中指定时,只有第一个匹配的文档将被更新。当在UpdateManyModel 中指定时,所有匹配的文档都将被更新。类型: Document |
更新 | 要执行的操作。 类型: UpdateModifications |
array_filters | (可选) 一组过滤器,指定在更新数组值字段时应用更新的数组元素。 类型: Array |
collation | (可选) 用于排序结果的排序规则。要了解更多关于排序规则的信息,请参阅排序规则指南。 类型: Document |
hint | (可选) 用于操作的索引。要了解更多关于索引的信息,请参阅索引指南。 类型: Bson |
upsert | (可选) 如果没有文档匹配过滤器,是否创建新文档。默认情况下,此字段设置为 false 。类型: bool |
示例
此示例执行以下操作
指定一个数组中的
UpdateOneModel
和UpdateManyModel
实例。这些模型包含更新表示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
删除
要执行批量删除操作,为每个删除操作创建一个 DeleteOneModel
或 DeleteManyModel
实例。然后,将模型列表传递给 bulk_write()
方法。一个 DeleteOneModel
仅删除匹配过滤器的单个文档,而一个 DeleteManyModel
删除所有匹配过滤器的文档。
以下表格描述了您可以调用其相应构建器方法设置的 DeleteOneModel
和 DeleteManyModel
字段
字段 | 描述 |
---|---|
namespace | 执行操作的命名空间。 类型: Namespace |
filter | 匹配您想要删除的一个或多个文档的过滤器。当在 DeleteOneModel 中指定时,仅删除第一个匹配的文档。当在 DeleteManyModel 中指定时,将删除所有匹配的文档。类型: Document |
collation | (可选) 用于排序结果的排序规则。要了解更多关于排序规则的信息,请参阅排序规则指南。 类型: Document |
hint | (可选) 用于操作的索引。要了解更多关于索引的信息,请参阅索引指南。 类型: Bson |
示例
此示例执行以下操作
指定一个数组中的
DeleteOneModel
和DeleteManyModel
实例。这些模型包含在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
更多信息
有关批量操作的更多信息,请参阅服务器手册中的批量写入操作。