Overview
在本指南中,您可以学习;了解如何使用.NET/ C#驱动程序执行批量写入操作。通过使用批量写入操作,您可以通过更少的数据库调用来执行多个写入操作。
考虑需要为同一任务插入文档、更新文档和删除文档的情况。 如果使用单独的写入方法执行每种类型的操作,则每次写入都会单独访问数据库。 您可以使用批量写入操作来优化应用程序对服务器的调用次数。
您可以使用 IMongoCollection.BulkWrite() 或 IMongoCollection.BulkWriteAsync() 方法对单个集合执行批量写入操作。每个方法都有一个 WriteModel<TDocument> 实例列表,这些实例描述要执行的写入操作。
样本数据
sample_restaurants.restaurants本指南中的示例使用Atlas示例数据集中的 集合。要学习;了解如何创建免费的MongoDB Atlas 群集并加载示例数据集,请参阅快速入门教程。
定义写入操作
对于要执行的每个写入操作,请创建以下 WriteModel<TDocument> 类之一的实例:
DeleteManyModel<TDocument>DeleteOneModel<TDocument>InsertOneModel<TDocument>ReplaceOneModel<TDocument>UpdateManyModel<TDocument>UpdateOneModel<TDocument>
以下部分介绍如何创建并使用上述类的实例,以在批量写入操作中执行相应的写入操作。
提示
使用 POCO 进行批量写入操作
本指南中的示例在所有泛型类中使用 BsonDocument 类型作为 TDocument 类型。您还可以对这些类使用普通旧 CLR 对象 (POCO)。 为此,必须定义一个类来表示集合中的文档。 该类必须具有与文档中的字段匹配的属性。 有关更多信息,请参阅 POCO。
插入操作
要执行插入操作,请创建一个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 类包含以下属性,它们表示可用于配置批量写入操作的选项:
属性 | 说明 |
|---|---|
| 指定操作是否绕过文档级验证。有关详细信息,请参阅 MongoDB Server 手册中的 模式验证 。 |
| 以 |
| 如果 |
|
以下代码示例使用 BulkWriteOptions对象执行无序批量写入操作:
返回值
BulkWrite() 和 BulkWriteAsync() 方法返回包含以下属性的 BulkWriteResult对象:
属性 | 说明 |
|---|---|
| 指示服务器是否确认了批量写入操作。如果此属性的值为 |
| 删除的文档数量(如有)。 |
| 插入的文档数量(如有)。 |
| 更新匹配的文档数(如有)。 |
| 已修改文档的数量(如有)。 |
| 指示修改后的计数是否可用。 |
| 包含有关导致更新或插入(upsert)操作的每个请求的信息的列表。 |
| 批处理操作中的请求数。 |
处理异常
如果批量写入操作中的任何操作失败, .NET/ C#驱动程序会抛出 BulkWriteError,并且不会执行任何进一步的操作。
BulkWriteError对象包含 Index属性,该属性描述导致错误的请求的索引。
更多信息
要了解如何执行单个写入操作,请参阅以下指南:
要进一步了解本指南所讨论的任何方法或类型,请参阅以下 API 文档: