Overview
在本指南中,您可以学习;了解如何使用批量写入操作在单个数据库调用中执行多个写入操作。
考虑这样一个场景:您要插入一个文档,更新多个其他文档,然后删除一个文档。 如果使用单独的方法,则每个操作都需要调用自己的数据库。
通过使用批量写入操作,您可以通过更少的数据库调用来执行多个写入操作。 您可以在以下级别执行批量写入操作:
集合:您可以使用
IMongoCollection.BulkWrite()或IMongoCollection.BulkWriteAsync()方法对单个集合执行批量写入操作。这些方法对每种类型的写入操作进行数据库调用。示例,这些方法在一次调用中执行多个更新操作,但对数据库进行两次单独的调用以执行插入操作和替换操作。客户端:如果您的应用程序连接到MongoDB Server 8.0 或更高版本,则可以使用
IMongoClient.BulkWrite()或IMongoClient.BulkWriteAsync()方法对同一集群中的多个集合和数据库执行批量写入操作。此方法在一次数据库调用中执行所有写入操作。
样本数据
The examples in this guide use the sample_restaurants.restaurants and sample_mflix.movies collections from the Atlas sample datasets. To learn how to create a free MongoDB Atlas cluster and load the sample datasets, see the MongoDB Get Started guide.
提示
使用 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 文档:
客户端批量写入