批量操作
概述
在本指南中,您可以学习如何在MongoDB Java驱动程序中使用批量操作。
要执行创建、替换、更新或删除操作,请使用其对应的方法。例如,要向您的集合中插入一个文档、更新多个文档和删除一个文档,请使用以下方法:insertOne()
、updateMany()
和 deleteOne()
。
MongoClient
通过对数据库的每个操作进行一次调用来执行这些操作。您可以通过使用批量操作将数据库调用的数量减少到一次。
执行批量操作
批量操作包含大量写操作。要执行批量操作,请将一个 List
的 WriteModel
文档传递给 bulkWrite()
方法。一个 WriteModel
是一个表示任何写操作的模型。
以下部分展示了如何创建和使用每个 WriteModel
文档。每个部分中的示例使用以下文档在 people
集合中:
{ "_id": 1, "name": "Karen Sandoval", "age": 31 } { "_id": 2, "name": "William Chin", "age": 54 } { "_id": 8, "name": "Shayla Ray", "age": 20 }
有关本节中提到的方法和类的更多信息,请参阅以下API文档:
插入操作
要执行插入操作,创建一个指定要插入的文档的 InsertOneModel
。要插入多个文档,必须为要插入的每个文档创建一个 InsertOneModel
。
示例
以下示例创建了一个用于描述人的两个文档的 InsertOneModel
。
InsertOneModel<Document> juneDoc = new InsertOneModel<>(new Document("name", "June Carrie") .append("age", 17)); InsertOneModel<Document> kevinDoc = new InsertOneModel<>(new Document("name", "Kevin Moss") .append("age", 22));
重要
当执行 bulkWrite()
时,InsertOneModel
不能插入具有已在集合中存在的 _id
的文档。相反,该方法会抛出 MongoBulkWriteException
。
以下示例尝试插入具有 _id
为 1
和 3
的两个文档
try { List<WriteModel<Document>> bulkOperations = new ArrayList<>(); // Creates instructions to insert documents InsertOneModel<Document> doc1 = new InsertOneModel<>(new Document("_id", 1)); InsertOneModel<Document> doc3 = new InsertOneModel<>(new Document("_id", 3)); bulkOperations.add(doc1); bulkOperations.add(doc3); // Runs a bulk write operation for the specified insert WriteModels collection.bulkWrite(bulkOperations); // Prints a message if any exceptions occur during the bulk write operation } catch (MongoBulkWriteException e){ System.out.println("A MongoBulkWriteException occurred with the following message: " + e.getMessage()); }
以下显示了上述代码的输出
A MongoBulkWriteException occurred with the following message: Bulk write operation error on server sample-shard-00-02.pw0q4.mongodb.net:27017. Write errors: [BulkWriteError{index=0, code=11000, message='E11000 duplicate key error collection: crudOps.bulkWrite index: _id_ dup key: { _id: 1 }', details={}}].
要了解为什么 _id
为 3
的文档没有插入,请参阅 执行顺序 部分。
有关本节中提到的方法和类的更多信息,请参阅 InsertOneModel API 文档。
替换操作
要执行替换操作,创建一个指定要替换的文档查询过滤器的 ReplaceOneModel
。
重要
当执行 bulkWrite()
时,ReplaceOneModel
不能更改违反集合唯一索引约束的文档,并且如果没有匹配到查询过滤器,则模型不会替换文档。
示例
以下示例创建一个 ReplaceOneModel
,用于替换 _id
为 1
的文档,该文档包含一个新增的 location
字段
ReplaceOneModel<Document> celineDoc = new ReplaceOneModel<>( Filters.eq("_id", 1), new Document("name", "Celine Stork") .append("location", "San Diego, CA"));
有关本节中提到的方法和类的更多信息,请参阅以下资源
ReplaceOneModel API 文档
唯一索引 服务器手册说明
更新操作
要执行更新操作,请创建一个指定查询过滤器以更新文档及其更新的内容的 UpdateOneModel
或 UpdateManyModel
。
UpdateOneModel
更新与查询过滤器匹配的第一个文档,而 UpdateManyModel
更新与查询过滤器匹配的所有文档。
重要
执行 bulkWrite()
时,UpdateOneModel
和 UpdateManyModel
不能更改违反集合唯一索引约束的文档,并且如果没有匹配查询过滤器的文档,则模型不会更新任何文档。
示例
以下示例创建了一个 UpdateOneModel
来更新 age
字段,条件是文档的 _id
为 2
UpdateOneModel<Document> updateDoc = new UpdateOneModel<>( Filters.eq("_id", 2), Updates.set("age", 31));
有关本节中提到的方法和类的更多信息,请参阅以下资源
UpdateOneModel API 文档
UpdateManyModel API 文档
唯一索引 服务器手册解释
删除操作
要执行删除操作,创建一个指定要删除的文档查询过滤器的 DeleteOneModel
或 DeleteManyModel
。
DeleteOneModel
删除与查询过滤器匹配的第一个文档,而 DeleteManyModel
删除与查询过滤器匹配的所有文档。
重要
执行 bulkWrite()
时,如果查询过滤器没有匹配项,则 DeleteOneModel
和 DeleteManyModel
不会删除任何文档。
示例
以下示例创建了一个用于删除 _id
为 1
的文档的 DeleteOneModel
。
DeleteOneModel<Document> deleteDoc = new DeleteOneModel<>(Filters.eq("_id", 1));
有关本节中提到的方法和类的更多信息,请参阅以下API文档:
执行顺序
bulkWrite()
方法接受一个可选的 BulkWriteOptions
作为第二个参数,用于指定批量操作的执行是按顺序还是无序。
按顺序执行
默认情况下,bulkWrite()
方法按顺序执行批量操作。这意味着批量操作将按照你添加到列表中的顺序执行,直到发生错误(如果有)。
示例
以下示例执行以下批量操作
一个插入操作,插入一个具有
name
值为"Zaynab Omar"
和age
值为37
的文档一个替换操作,替换
_id
为1
的文档,该文档包含location
字段一个操作,用于更新文档,将
name
值更改为"Zaynab Omar"
并将name
改为"Zaynab Hassan"
一个操作,删除所有
age
值大于50
的文档
List<WriteModel<Document>> bulkOperations = new ArrayList<>(); // Creates instructions to insert a document InsertOneModel<Document> insertDoc = new InsertOneModel<>(new Document("_id", 6) .append("name", "Zaynab Omar") .append("age", 37)); // Creates instructions to replace the first document matched by the query ReplaceOneModel<Document> replaceDoc = new ReplaceOneModel<>(Filters.eq("_id", 1), new Document("name", "Sandy Kane") .append("location", "Helena, MT")); // Creates instructions to update the first document matched by the query UpdateOneModel<Document> updateDoc = new UpdateOneModel<>(Filters.eq("name", "Zaynab Omar"), Updates.set("name", "Zaynab Hassan")); // Creates instructions to delete all documents matched by the query DeleteManyModel<Document> deleteDoc = new DeleteManyModel<>(Filters.gt("age", 50)); bulkOperations.add(insertDoc); bulkOperations.add(replaceDoc); bulkOperations.add(updateDoc); bulkOperations.add(deleteDoc); // Runs a bulk write operation for the specified the insert, replace, update, and delete WriteModels in order collection.bulkWrite(bulkOperations);
运行此示例后,您的集合包含以下文档
{ "_id": 1, "name": "Sandy Kane", "location": "Helena, MT" } { "_id": 8, "name": "Shayla Ray", "age": 20 } { "_id": 6, "name": "Zaynab Hassan", "age": 37 }
无序执行
您还可以通过在 BulkWriteOptions
的 order()
方法中指定 "false" 来以任何顺序执行批量操作。这意味着所有写操作都会执行,无论是否出错,如果有错误发生,批量操作会在最后报告它们。
在先前的示例中添加以下内容,指定批量操作以任何顺序执行
BulkWriteOptions options = new BulkWriteOptions().ordered(false); // Runs a bulk write operation for the specified insert, replace, update, and delete WriteModels in any order collection.bulkWrite(bulkOperations, options);
注意
无序批量操作不保证执行顺序。顺序可能因优化运行时而有所不同。
在先前的示例中,如果 bulkWrite()
方法决定在更新操作之后执行插入操作,由于此时文档不存在,更新操作不会受到影响。您的集合随后包含以下文档
{ "_id": 1, "name": "Sandy Kane", "location": "Helena, MT" } { "_id": 8, "name": "Shayla Ray", "age": 20 } { "_id": 6, "name": "Zaynab Omar", "age": 37 }
有关本节中提到的方法和类的更多信息,请参阅以下API文档:
总结
要执行批量操作,您创建一个包含 WriteModel
文档的列表,并将其传递给 bulkWrite()
方法。
有 6 种不同的 WriteModel
文档:InsertOneModel
、ReplaceOneModel
、UpdateOneModel
、UpdateManyModel
、DeleteOneModel
和 DeleteManyModel
。
执行 bulkWrite()
方法有两种方式
有序,按顺序执行批量操作,直到发生错误(如果有任何错误发生)
无序,按任何顺序执行所有批量操作,如果有错误发生,则在最后报告错误