批量写入操作
概述
在本指南中,您将学习如何通过使用 批量写入操作 在单个数据库调用中执行多个写入操作。
考虑以下场景:您想将一个文档插入到一个集合中,更新多个其他文档,然后删除一个文档。如果您使用单独的方法,每个操作都需要自己的数据库调用。本指南将向您展示如何使用批量写入操作来减少对数据库的调用次数。
示例数据
本指南中的示例使用的是sample_restaurants.restaurants
集合来自Atlas 示例数据集。要了解如何创建免费的 MongoDB Atlas 集群并加载示例数据集,请参阅入门教程。
重要
项目 Reactor 库
本指南使用Project Reactor库来消费由Java反应式流驱动方法返回的Publisher
实例。要了解有关Project Reactor库及其使用方法,请参阅Reactor文档中的入门指南。要了解本指南中如何使用Project Reactor库的方法,请参阅写入MongoDB数据指南。
定义写操作
对于您想要执行的每个写操作,创建以下类之一的一个实例
InsertOneModel
UpdateOneModel
UpdateManyModel
ReplaceOneModel
DeleteOneModel
DeleteManyModel
然后,将这些实例的列表传递给bulkWrite()
方法。
以下部分将展示如何创建和使用这些类的实例。
插入操作
要执行插入操作,创建一个InsertOneModel
实例,并传入您想要插入的文档。
以下示例创建了一个InsertOneModel
实例
InsertOneModel<Document> operation = new InsertOneModel<>( new Document("name", "Mongo's Deli") .append("cuisine", "Sandwiches"));
要插入多个文档,为每个文档创建一个InsertOneModel
实例。
更新操作
要更新一个文档,创建一个UpdateOneModel
实例,并传入以下参数
查询过滤器,用于指定匹配您集合中文档的准则。
要执行的操作。有关更新操作的信息,请参阅MongoDB服务器手册中的字段更新运算符指南。
UpdateOneModel
更新与您的查询过滤器匹配的第一个文档。
以下示例创建了一个UpdateOneModel
实例
UpdateOneModel<Document> operation = new UpdateOneModel<>( eq("name", "Mongo's Deli"), set("cuisine", "Sandwiches and Salads"));
要更新多个文档,创建一个UpdateManyModel
实例,并传入相同的参数。UpdateManyModel
更新与您的查询过滤器匹配的所有文档。
以下示例创建了一个UpdateManyModel
实例
UpdateManyModel<Document> operation = new UpdateManyModel<>( eq("name", "Mongo's Deli"), set("cuisine", "Sandwiches and Salads"));
替换操作
替换操作会移除指定文档的所有字段和值(除了 _id
字段),并用新的值替换它们。要执行替换操作,创建一个 ReplaceOneModel
实例,并传入查询过滤器以及你想要存储在匹配文档中的字段和值。
以下示例创建了 ReplaceOneModel
的实例
ReplaceOneModel<Document> operation = new ReplaceOneModel<>( eq("name", "Original Pizza"), new Document("name", "Mongo's Pizza") .append("borough", "Manhattan"));
要替换多个文档,为每个文档创建一个 ReplaceOneModel
实例。
删除操作
要删除文档,创建一个 DeleteOneModel
实例,并传入指定要删除的文档的查询过滤器。DeleteOneModel
只会删除匹配查询过滤器的第一个文档。
以下示例创建了 DeleteOneModel
的实例
DeleteOneModel<Document> operation = new DeleteOneModel<>( eq("restaurant_id", "5678"));
要删除多个文档,创建一个 DeleteManyModel
实例,并传入指定要删除的文档的查询过滤器。DeleteManyModel
会删除所有匹配查询过滤器的文档。
以下示例创建了 DeleteManyModel
的实例
DeleteManyModel<Document> operation = new DeleteManyModel<>( eq("name", "Mongo's Deli"));
调用 bulkWrite()
方法
定义每个要执行的操作的类实例后,将这些实例的列表传递给 bulkWrite()
方法。默认情况下,该方法按照列表中定义的顺序执行操作。
以下示例通过使用 bulkWrite()
方法执行多个写操作
Publisher<BulkWriteResult> bulkWritePublisher = restaurants.bulkWrite( Arrays.asList(new InsertOneModel<>( new Document("name", "Mongo's Deli") .append("cuisine", "Sandwiches") .append("borough", "Manhattan") .append("restaurant_id", "1234")), new InsertOneModel<>(new Document("name", "Mongo's Deli") .append("cuisine", "Sandwiches") .append("borough", "Brooklyn") .append("restaurant_id", "5678")), new UpdateManyModel<>(eq("name", "Mongo's Deli"), set("cuisine", "Sandwiches and Salads")), new DeleteOneModel<>(eq("restaurant_id", "1234")))); BulkWriteResult bulkResult = Mono.from(bulkWritePublisher).block(); System.out.println(bulkResult.toString());
AcknowledgedBulkWriteResult{insertedCount=2, matchedCount=2, removedCount=1, modifiedCount=2, upserts=[], inserts=[BulkWriteInsert{index=0, id=BsonObjectId{value=66a7e0a6c08025218b657208}}, BulkWriteInsert{index=1, id=BsonObjectId{value=66a7e0a6c08025218b657209}}]}
如果任何写操作失败,Java Reactive Streams 驱动程序将发出一个 MongoBulkWriteException
,并且不会执行任何其他单个操作。MongoBulkWriteException
包含一个 BulkWriteError
,可以通过使用 MongoBulkWriteException.getWriteErrors()
方法访问,该方法提供了单个失败的详细信息。
注意
当 Java Reactive Streams 驱动程序运行批量操作时,它使用正在运行操作的集合的 writeConcern
。驱动程序在尝试所有操作后报告所有写关注错误,无论执行顺序如何。
自定义批量写操作
BulkWriteOptions
类包含修改 bulkWrite()
方法行为的方法。要使用 BulkWriteOptions
类,构造该类的新实例,然后调用其一或多个方法来修改写操作。您可以链接这些方法调用。要将类实例作为最后一个参数传递给 bulkWrite()
方法以修改写操作的行为。
您可以在BulkWriteOptions
类中使用以下方法来修改写操作。所有方法都是可选的。
方法 | 描述 |
---|---|
bypassDocumentValidation(Boolean bypassDocumentValidation) | 指定批量写操作是否绕过文档验证。这允许您对不符合模式验证要求的文档执行写操作(如果存在)。有关模式验证的更多信息,请参阅MongoDB服务器手册中的模式验证。 |
comment(Bson comment) | 将 Bson 注释附加到操作。有关更多信息,请参阅MongoDB服务器手册中的插入命令字段指南。 |
comment(String comment) | 将 String 注释附加到操作。有关更多信息,请参阅MongoDB服务器手册中的插入命令字段指南。 |
let(Bson variables) | 指定参数名称和值的映射。值必须是常量或封闭表达式,不能引用文档字段。有关更多信息,请参阅MongoDB服务器手册中的let语句。 |
ordered(Boolean ordered) | 如果设置为 True ,驱动程序将按提供的顺序执行单个操作。如果单个操作失败,驱动程序将不会执行任何后续的单个操作。默认为 True 。 |
以下示例调用前面示例中的bulkWrite()
方法,但将ordered
选项设置为False
Publisher<BulkWriteResult> bulkWritePublisher = restaurants.bulkWrite( Arrays.asList(new InsertOneModel<>( new Document("name", "Mongo's Deli") .append("cuisine", "Sandwiches") .append("borough", "Manhattan") .append("restaurant_id", "1234")), new InsertOneModel<>(new Document("name", "Mongo's Deli") .append("cuisine", "Sandwiches") .append("borough", "Brooklyn") .append("restaurant_id", "5678")), new UpdateManyModel<>(eq("name", "Mongo's Deli"), set("cuisine", "Sandwiches and Salads")), new DeleteOneModel<>(eq("restaurant_id", "1234"))), new BulkWriteOptions().ordered(false)); BulkWriteResult bulkResult = Mono.from(bulkWritePublisher).block(); System.out.println(bulkResult.toString());
AcknowledgedBulkWriteResult{insertedCount=2, matchedCount=2, removedCount=1, modifiedCount=2, upserts=[], inserts=[BulkWriteInsert{index=0, id=BsonObjectId{value=66a7e03cce430c5854b6caf9}}, BulkWriteInsert{index=1, id=BsonObjectId{value=66a7e03cce430c5854b6cafa}}]}
如果无序批量写操作中的任何写操作失败,Java Reactive Streams驱动程序将在尝试所有操作后报告错误。
注意
无序批量操作不保证执行顺序。顺序可能因优化运行时而有所不同。
更多信息
要了解如何执行单个写操作,请参阅以下指南
API 文档
要了解更多关于本指南中讨论的任何方法或类型,请参阅以下 API 文档