Overview
在本指南中,您可以了解如何在 MongoDB Java 驱动程序中使用批量操作。
要执行创建、替换、更新或删除操作,请使用相应的方法。例如,要在集合中插入一个文档、更新多个文档和删除一个文档,可使用 insertOne()、updateMany() 和 deleteOne() 方法。
在执行这些操作时,MongoClient 会对数据库调用每个操作。您可使用批量操作,将对数据库的调用次数减少到一次。
执行批量操作
批量操作包括大量写操作。要执行批量操作,请向 bulkWrite() 方法传递 List 文档的 WriteModel。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,用包含新增 location 字段的文档替换 _id 为 1 的文档:
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 不会删除任何文件。
例子
以下示例创建 DeleteOneModel 来删除 _id 为 1 的文档:
DeleteOneModel<Document> deleteDoc = new DeleteOneModel<>(Filters.eq("_id", 1));
有关本节中提到的方法和类的详情,请参阅以下 API 文档:
执行顺序
bulkWrite() 方法接受可选的 BulkWriteOptions 作为第二个参数,以指定批量操作是有序执行还是无序执行。
命令执行
默认情况下,bulkWrite() 方法按顺序执行批量操作。这意味着批量操作将按照您添加到列表中的顺序执行,直到出现错误(如有)。
例子
以下示例执行这些批量操作:
一个操作,插入
name值为"Zaynab Omar"且age值为37的文档一个操作,将
_id为1的文档替换为包含location字段的新文档一个操作,使用
"Zaynab Omar"的name值更新文档并将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() 方法:
有序,按顺序执行批量操作,直到出现错误(如有)
无序,以任何顺序执行所有批量操作,并在最后报告错误(如果有)