Overview
在本指南中,您可以学习;了解如何使用批量写入操作在单个数据库调用中执行多个写入操作。
考虑这样一个场景:您要插入一个文档,更新多个其他文档,然后删除一个文档。 如果使用单独的方法,则每个操作都需要调用自己的数据库。
通过使用批量写入操作,您可以通过更少的数据库调用来执行多个写入操作。 您可以在以下级别执行批量写入操作:
样本数据
本指南中的示例使用Atlas示例数据集中的 和sample_restaurants.restaurants sample_mflix.movies集合。要学习;了解如何创建免费的MongoDB Atlas 群集并加载示例数据集,请参阅MongoDB入门指南。
提示
使用 POCO 进行批量写入操作
本指南中的示例在所有泛型类中使用 BsonDocument 类型作为 TDocument 类型。您还可以对这些类使用普通旧 CLR 对象 (POCO)。 为此,必须定义一个类来表示集合中的文档。 该类必须具有与文档中的字段匹配的属性。 有关更多信息,请参阅 POCO。
集合批量写入
批量写入操作包含一个或多个写入操作。对于要执行的每个写入操作,请创建以下 WriteModel<TDocument> 类之一的实例:
DeleteManyModel<TDocument>DeleteOneModel<TDocument>InsertOneModel<TDocument>ReplaceOneModel<TDocument>UpdateManyModel<TDocument>UpdateOneModel<TDocument>
以下部分介绍如何创建并使用上述类的实例,以在批量写入操作中执行相应的写入操作。执行批量操作部分演示了如何将模型列表传递给 BulkWrite()或BulkWriteAsync() 方法以执行批量操作。
插入操作
要执行插入操作,请创建一个InsertOneModel<TDocument>实例并指定要插入的文档。
以下示例创建了 InsertOneModel<BsonDocument> 类的实例。此实例指示驱动程序将 "name"字段为 "Mongo's Deli" 的文档插入到 restaurants集合中。
var insertOneModel = new InsertOneModel<BsonDocument>( new BsonDocument{ { "name", "Mongo's Deli" }, { "cuisine", "Sandwiches" }, { "borough", "Manhattan" }, { "restaurant_id", "1234" } } );
要插入多个文档,请为每个文档创建一个InsertOneModel<TDocument>实例。
重要
重复键错误
执行批量操作时,InsertOneModel<TDocument> 无法插入集合中已存在的具有 _id 的文档。在这种情况下,驱动程序会抛出 MongoBulkWriteException。
更新操作
要更新单个文档,请创建 UpdateOneModel<TDocument> 的实例并传递以下参数:
查询过滤,指定用于匹配集合中文档的条件。要学习;了解有关指定查询的更多信息,请参阅MongoDB Server手册中的查询和投影操作符。
描述要执行的更新的更新文档。要学习;了解有关指定更新的更多信息,请参阅MongoDB Server手册中的 Update Operators。
UpdateOneModel<TDocument>实例指定与查询过滤匹配的第一个文档的更新。
在以下代码示例中,UpdateOneModel<BsonDocument>对象表示 restaurants集合上的更新操作。该操作匹配集合中 name字段的值为 "Mongo's Deli" 的第一个文档。然后,它将匹配文档中 cuisine字段的值更新为 "Sandwiches and Salads"。
var updateOneModel = new UpdateOneModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli"), Builders<BsonDocument>.Update.Set("cuisine", "Sandwiches and Salads") );
要更新多个文档,请创建UpdateManyModel<TDocument>的实例并传递与UpdateOneModel<TDocument>相同的参数。 UpdateManyModel<TDocument>类指定与查询过滤匹配的所有文档的更新。
在以下代码示例中,UpdateManyModel<BsonDocument>对象表示 restaurants集合上的更新操作。该操作匹配集合中 name字段的值为 "Mongo's Deli" 的所有文档。然后,它将 cuisine字段的值更新为 "Sandwiches and Salads"。
var updateManyModel = new UpdateManyModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli"), Builders<BsonDocument>.Update.Set("cuisine", "Sandwiches and Salads") );
替换操作
替换操作会删除指定文档的所有字段和值,并将其替换为您指定的新字段和值。 要执行替换操作,请创建ReplaceOneModel<TDocument>实例并传递查询过滤以及要用于替换匹配文档的字段和值。
在以下示例中,ReplaceOneModel<BsonDocument>对象表示 restaurants集合上的替换操作。该操作匹配集合中 restaurant_id字段值为 "1234" 的文档。然后,它会从此文档中删除 _id 以外的所有字段,并在 name、cuisine、borough 和 restaurant_id 字段中设置新值。
var replaceOneModel = new ReplaceOneModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("restaurant_id", "1234"), new BsonDocument{ { "name", "Mongo's Pizza" }, { "cuisine", "Pizza" }, { "borough", "Brooklyn" }, { "restaurant_id", "5678" } } );
要替换多个文档,必须为每个文档创建一个ReplaceOneModel<TDocument>实例。
删除操作
要删除文档,请创建DeleteOneModel<TDocument>的实例并传递查询过滤,指定要删除的文档。 DeleteOneModel<TDocument>实例提供了仅删除与查询过滤匹配的第一个文档的说明。
在以下代码示例中,DeleteOneModel<BsonDocument>对象表示 restaurants集合上的删除操作。该操作匹配并删除 restaurant_id字段的值为 "5678" 的第一个文档。
var deleteOneModel = new DeleteOneModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("restaurant_id", "5678") );
要删除多个文档,请创建 DeleteManyModel<TDocument> 的实例并传递查询过滤,指定要删除的文档。DeleteManyModel<TDocument> 的实例提供了删除与查询过滤匹配的所有文档的说明。
在以下代码示例中,DeleteManyModel<BsonDocument>对象表示 restaurants集合上的删除操作。该操作会匹配并删除 name字段的值为 "Mongo's Deli" 的所有文档。
var deleteManyModel = new DeleteManyModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli") );
执行批量操作
为要执行的每个操作定义 WriteModel实例后,创建一个实现 IEnumerable 接口的类的实例。将您的 WriteModel 对象添加到此 IEnumerable,然后将 IEnumerable 传递给 BulkWrite() 或 BulkWriteAsync() 方法。默认下,这些方法按照列表中定义的顺序运行操作。
提示
IEnumerable
Array 和 List 是实现IEnumerable 接口的两个常用类。
从以下标签页中进行选择,查看如何使用同步 BulkWrite() 方法和异步 BulkWriteAsync() 方法对 restaurants集合执行批量写入操作:
var models = new List<WriteModel<BsonDocument>> { new InsertOneModel<BsonDocument>( new BsonDocument{ { "name", "Mongo's Deli" }, { "cuisine", "Sandwiches" }, { "borough", "Manhattan" }, { "restaurant_id", "1234" } } ), new InsertOneModel<BsonDocument>( new BsonDocument{ { "name", "Mongo's Deli" }, { "cuisine", "Sandwiches" }, { "borough", "Brooklyn" }, { "restaurant_id", "5678" } } ), new UpdateManyModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli"), Builders<BsonDocument>.Update.Set("cuisine", "Sandwiches and Salads") ), new DeleteOneModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("restaurant_id", "1234") ) }; var results = collection.BulkWrite(models); Console.WriteLine(results);
var models = new List<WriteModel<BsonDocument>> { new InsertOneModel<BsonDocument>( new BsonDocument{ { "name", "Mongo's Deli" }, { "cuisine", "Sandwiches" }, { "borough", "Manhattan" }, { "restaurant_id", "1234" } } ), new InsertOneModel<BsonDocument>( new BsonDocument{ { "name", "Mongo's Deli" }, { "cuisine", "Sandwiches" }, { "borough", "Brooklyn" }, { "restaurant_id", "5678" } } ), new UpdateManyModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli"), Builders<BsonDocument>.Update.Set("cuisine", "Sandwiches and Salads") ), new DeleteOneModel<BsonDocument>( Builders<BsonDocument>.Filter.Eq("restaurant_id", "1234") ) }; var results = await collection.BulkWriteAsync(models); Console.WriteLine(results);
前面的代码示例生成以下输出:
MongoDB.Driver.BulkWriteResult1+Acknowledged[MongoDB.Bson.BsonDocument]
注意
当驱动程序运行批量操作时,它会使用目标集合的写关注(write concern)。无论执行顺序如何,驱动程序在尝试所有操作后都会报告所有写关注(write concern)错误。
自定义批量写入操作
调用 BulkWrite() 或 BulkWriteAsync() 方法时,可以传递 BulkWriteOptions 类的实例。BulkWriteOptions 类包含以下属性,它们表示可用于配置批量写入操作的选项:
属性 | 说明 |
|---|---|
| |
| |
| 如果 |
|
以下代码示例使用 BulkWriteOptions对象执行无序批量写入操作:
返回值
BulkWrite() 和 BulkWriteAsync() 方法返回包含以下属性的 BulkWriteResult对象:
属性 | 说明 |
|---|---|
| 指示服务器是否确认了批量写入操作。如果此属性的值为 |
| 删除的文档数量(如有)。 |
| 插入的文档数量(如有)。 |
| 更新匹配的文档数(如有)。 |
| 已修改文档的数量(如有)。 |
| 指示修改后的计数是否可用。 |
| 包含有关导致更新或插入(upsert)操作的每个请求的信息的列表。 |
| 批处理操作中的请求数。 |
处理异常
如果批量写入操作中的任何操作失败, .NET/ C#驱动程序会抛出 BulkWriteError,并且不会执行任何进一步的操作。
BulkWriteError对象包含 Index属性,该属性描述导致错误的请求的索引。
客户端批量写入
连接到运行MongoDB Server 8.0 或更高版本的部署时,可以使用 IMongoClient.BulkWrite() 或 IMongoClient.BulkWriteAsync() 方法写入同一集群中的多个数据库和集合。这些方法在一次调用中执行所有写入操作。
对于要执行的每个写入操作,请创建以下 BulkWriteModel 类之一的实例:
BulkWriteInsertOneModel<TDocument>BulkWriteUpdateOneModel<TDocument>BulkWriteUpdateManyModel<TDocument>BulkWriteReplaceOneModel<TDocument>BulkWriteDeleteOneModel<TDocument>BulkWriteDeleteManyModel<TDocument>
以下部分介绍如何创建并使用上述类的实例,以批量写入的形式执行相应的写入操作。执行批量操作部分演示了如何将模型列表传递给 BulkWrite()或BulkWriteAsync() 方法以执行批量操作。
插入操作
要执行插入操作,请创建 BulkWriteInsertOneModel<TDocument> 类的实例。BulkWriteInsertOneModel<TDocument> 构造函数接受以下参数:
Parameter | 说明 |
|---|---|
| 要在其中插入BSON文档的数据库和集合。数据类型: |
| 要插入集合的文档。 |
以下示例创建 BulkWriteInsertOneModel<TDocument> 类的实例。这些实例指示驱动程序将文档插入到 sample_restaurants.restaurants 和 sample_mflix.movies 集合中。
var restaurantToInsert = new BulkWriteInsertOneModel<BsonDocument>( "sample_restaurants.restaurants", new BsonDocument{ { "name", "Mongo's Deli" }, { "cuisine", "Sandwiches" }, { "borough", "Manhattan" }, { "restaurant_id", "1234" } } ); var movieToInsert = new BulkWriteInsertOneModel<BsonDocument>( "sample_mflix.movies", new BsonDocument{ { "title", "Silly Days" }, { "year", 2022 } } );
更新操作
要更新单个文档,请创建 BulkWriteUpdateOneModel<TDocument> 类的实例。BulkWriteUpdateOneModel<TDocument> 构造函数接受以下参数:
Parameter | 说明 |
|---|---|
| 要在其中插入BSON文档的数据库和集合。数据类型: |
|
|
| 要执行的更新操作。有关更新操作的更多信息,请参阅MongoDB |
| |
| |
| |
|
在以下代码示例中,BulkWriteUpdateOneModel<BsonDocument> 对象表示对 sample_restaurants.restaurants 和 sample_mflix.movies 集合的更新操作。
var restaurantUpdate = new BulkWriteUpdateOneModel<BsonDocument>( "sample_restaurants.restaurants", Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli"), Builders<BsonDocument>.Update.Set("cuisine", "Sandwiches and Salads") ); var movieUpdate = new BulkWriteUpdateOneModel<BsonDocument>( "sample_mflix.movies", Builders<BsonDocument>.Filter.Eq("title", "Carrie"), Builders<BsonDocument>.Update.Set("seen", True) );
要更新多个文档,请创建 BulkWriteUpdateManyModel<TDocument> 类的实例。此类的构造函数接受与 BulkWriteUpdateOneModel<TDocument> 构造函数相同的参数。BulkWriteUpdateManyModel<TDocument>操作会更新与查询过滤匹配的所有文档。
在以下代码示例中,BulkWriteUpdateManyModel<BsonDocument>对象表示 sample_restaurants.restaurants集合上的更新操作。该操作匹配集合中 name字段的值为 "Starbucks" 的所有文档。然后,它将 cuisine字段的值更新为 "Coffee (Chain)"。
var updateManyModel = new BulkWriteUpdateManyModel<BsonDocument>( "sample_restaurants.restaurants", Builders<BsonDocument>.Filter.Eq("name", "Starbucks"), Builders<BsonDocument>.Update.Set("cuisine", "Coffee (Chain)") );
替换操作
要替换文档中的字段,请创建 BulkWriteReplaceOneModel<TDocument> 类的实例。BulkWriteReplaceOneModel<TDocument> 构造函数接受以下参数:
Parameter | 说明 |
|---|---|
| 要在其中插入BSON文档的数据库和集合。数据类型: |
|
|
| 替换文档,用于指定要插入目标文档的字段和值。 |
| |
| |
|
在以下示例中,BulkWriteReplaceOneModel<BsonDocument> 对象表示对 sample_restaurants.restaurants 和 sample_mflix.movies 集合的替换操作。
var restaurantReplacement = new BulkWriteReplaceOneModel<BsonDocument>( "sample_restaurants.restaurants", Builders<BsonDocument>.Filter.Eq("restaurant_id", "1234"), new BsonDocument{ { "name", "Mongo's Pizza" }, { "cuisine", "Pizza" }, { "borough", "Brooklyn" }, { "restaurant_id", "5678" } } ); var movieReplacement = new BulkWriteReplaceOneModel<BsonDocument>( "sample_mflix.movies", Builders<BsonDocument>.Filter.Eq("title", "Insomnia"), new BsonDocument{ { "name", "Loving Sylvie" }, { "year", 1999 } } );
删除操作
要删除文档,请创建 BulkWriteDeleteOneModel<TDocument> 类的实例。BulkWriteDeleteOneModel<TDocument> 构造函数接受以下参数:
Parameter | 说明 |
|---|---|
| 要在其中插入BSON文档的数据库和集合。数据类型: |
|
|
| |
|
在以下代码示例中,BulkWriteDeleteOneModel<BsonDocument> 对象表示对 sample_restaurants.restaurants 和 sample_mflix.movies 集合删除操作。
var restaurantToDelete = new BulkWriteDeleteOneModel<BsonDocument>( "sample_restaurants.restaurants", Builders<BsonDocument>.Filter.Eq("restaurant_id", "5678") ); var movieToDelete = new BulkWriteDeleteOneModel<BsonDocument>( "sample_mflix.movies", Builders<BsonDocument>.Filter.Eq("title", "Mr. Nobody") );
要删除多个文档,请创建 BulkWriteDeleteManyModel<TDocument> 类的实例,并传递指定要删除的文档的查询过滤。DeleteMany操作会删除与查询过滤匹配的所有文档。
在以下代码示例中,BulkWriteDeleteManyModel<BsonDocument>对象表示 sample_restaurants.restaurants集合上的删除操作。该操作会匹配并删除 name字段的值为 "Mongo's Deli" 的所有文档。
var deleteManyModel = new BulkWriteDeleteManyModel<BsonDocument>( "sample_restaurants.restaurants", Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli") );
执行批量操作
为要执行的每个操作定义 BulkWriteModel实例后,创建一个实现 IReadOnlyList 接口的类的实例。将您的 BulkWriteModel 对象添加到此 IReadOnlyList 中,然后将 IReadOnlyList 传递给 BulkWrite() 或 BulkWriteAsync() 方法。默认,这些方法按照在集合中定义的顺序运行操作。
提示
IReadOnlyList
Array 和 List 是实现IReadOnlyList 接口的两个常用类。
从以下标签页中进行选择,查看如何使用同步 BulkWrite() 方法和异步 BulkWriteAsync() 方法对多个命名空间执行批量写入操作。
var client = new MongoClient("mongodb://localhost:27017"); var restaurantNamespace = "sample_restaurants.restaurants"; var movieNamespace = "sample_mflix.movies"; var bulkWriteModels = new[] { new BulkWriteInsertOneModel<BsonDocument>( restaurantNamespace, new BsonDocument{ { "name", "Mongo's Deli" }, { "cuisine", "Sandwiches" }, { "borough", "Manhattan" }, { "restaurant_id", "1234" } } ), new BulkWriteInsertOneModel<BsonDocument>( movieNamespace, new BsonDocument{ { "name", "Sarah's Secret" }, { "year", 1988 } } ), new BulkWriteUpdateManyModel<BsonDocument>( restaurantNamespace, Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli"), Builders<BsonDocument>.Update.Set("cuisine", "Sandwiches and Salads") ), new BulkWriteDeleteOneModel<BsonDocument>( movieNamespace, Builders<BsonDocument>.Filter.Eq("title", "House") ) }; var result = client.BulkWrite(bulkWriteModels); Console.WriteLine(result);
var client = new MongoClient("mongodb://localhost:27017"); var restaurantNamespace = "sample_restaurants.restaurants"; var movieNamespace = "sample_mflix.movies"; var bulkWriteModels = new[] { new BulkWriteInsertOneModel<BsonDocument>( restaurantNamespace, new BsonDocument{ { "name", "Mongo's Deli" }, { "cuisine", "Sandwiches" }, { "borough", "Manhattan" }, { "restaurant_id", "1234" } } ), new BulkWriteInsertOneModel<BsonDocument>( movieNamespace, new BsonDocument{ { "name", "Sarah's Secret" }, { "year", 1988 } } ), new BulkWriteUpdateManyModel<BsonDocument>( restaurantNamespace, Builders<BsonDocument>.Filter.Eq("name", "Mongo's Deli"), Builders<BsonDocument>.Update.Set("cuisine", "Sandwiches and Salads") ), new BulkWriteDeleteOneModel<BsonDocument>( movieNamespace, Builders<BsonDocument>.Filter.Eq("title", "House") ) }; var result = await client.BulkWriteAsync(bulkWriteModels); Console.WriteLine(result);
前面的代码示例生成以下输出:
BulkWriteResult({'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 2, 'nModified': 2, 'nRemoved': 1, 'upserted': []}, acknowledged=True)
自定义批量写入
调用 BulkWrite() 或 BulkWriteAsync() 方法时,可以传递 ClientBulkWriteOptions 类的实例。ClientBulkWriteOptions 类包含以下属性,它们表示可用于配置批量写入操作的选项:
属性 | 说明 |
|---|---|
| |
| |
| 如果 |
| |
| 指定操作返回的 |
| 用于写入操作的写关注(write concern),作为 |
以下代码示例使用 ClientBulkWriteOptions对象自定义批量写入操作:
返回值
BulkWrite() 和 BulkWriteAsync() 方法返回包含以下属性的 ClientBulkWriteResult对象:
属性 | 说明 |
|---|---|
| 指示服务器是否确认了批量写入操作。如果此属性的值为 |
| 包含每个成功删除操作的结果(如果有)的 |
| 删除的文档数量(如有)。 |
| 一个包含每个成功插入操作结果(如有)的 |
| 插入的文档数量(如有)。 |
| 更新匹配的文档数(如有)。 |
| 已修改文档的数量(如有)。 |
| 一个包含每个成功更新操作的结果(如有)的 |
| 已更新或插入的文档数量(如有)。 |
处理异常
如果批量写入操作中的任何操作失败, .NET/ C#驱动程序会抛出 ClientBulkWriteException,并且不会执行任何进一步的操作。
ClientBulkWriteException对象包含以下属性:
属性 | 说明 |
|---|---|
| |
| 错误消息。 |
|
|
| |
| |
|
排序规则
要为操作配置排序规则,请创建 Collation 类的实例。
下表描述了 Collation 构造函数接受的参数。它还列出了相应的类属性,您可以使用这些属性读取每个设置的值。
Parameter | 说明 | 类属性 |
|---|---|---|
|
| |
| (可选)指定是否包含大小写比较。 |
|
|
|
|
| (可选)指定要执行的比较级别,如 ICU |
|
|
| |
|
|
|
| (可选)指定当 |
|
|
|
|
| (可选)指定包含变音符号的字符串是否从字符串的后部到前部排序。 |
|
有关排序规则的更多信息,请参阅MongoDB Server手册中的排序规则页面。
更多信息
要了解如何执行单个写入操作,请参阅以下指南:
API 文档
要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档:
客户端批量写入