文档菜单
文档首页
/ / /
Java 同步驱动程序
/ / /

批量操作

本页内容

  • 概述
  • 执行批量操作
  • 插入操作
  • 替换操作
  • 更新操作
  • 删除操作
  • 执行顺序
  • 有序执行
  • 无序执行
  • 总结

在本指南中,您可以学习如何在MongoDB Java驱动程序中使用批量操作。

要执行创建、替换、更新或删除操作,请使用其对应的方法。例如,要向您的集合中插入一个文档、更新多个文档和删除一个文档,请使用以下方法:insertOne()updateMany()deleteOne()

MongoClient 通过对数据库的每个操作进行一次调用来执行这些操作。您可以通过使用批量操作将数据库调用的数量减少到一次。

批量操作包含大量写操作。要执行批量操作,请将一个 ListWriteModel 文档传递给 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文档:

  • bulkWrite()

  • WriteModel

  • BulkWriteOptions

要执行插入操作,创建一个指定要插入的文档的 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

以下示例尝试插入具有 _id13 的两个文档

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={}}].

要了解为什么 _id3 的文档没有插入,请参阅 执行顺序 部分。

有关本节中提到的方法和类的更多信息,请参阅 InsertOneModel API 文档。

要执行替换操作,创建一个指定要替换的文档查询过滤器的 ReplaceOneModel

重要

当执行 bulkWrite() 时,ReplaceOneModel 不能更改违反集合唯一索引约束的文档,并且如果没有匹配到查询过滤器,则模型不会替换文档。

以下示例创建一个 ReplaceOneModel,用于替换 _id1 的文档,该文档包含一个新增的 location 字段

ReplaceOneModel<Document> celineDoc = new ReplaceOneModel<>(
Filters.eq("_id", 1),
new Document("name", "Celine Stork")
.append("location", "San Diego, CA"));

有关本节中提到的方法和类的更多信息,请参阅以下资源

要执行更新操作,请创建一个指定查询过滤器以更新文档及其更新的内容的 UpdateOneModelUpdateManyModel

UpdateOneModel 更新与查询过滤器匹配的第一个文档,而 UpdateManyModel 更新与查询过滤器匹配的所有文档。

重要

执行 bulkWrite() 时,UpdateOneModelUpdateManyModel 不能更改违反集合唯一索引约束的文档,并且如果没有匹配查询过滤器的文档,则模型不会更新任何文档。

以下示例创建了一个 UpdateOneModel 来更新 age 字段,条件是文档的 _id2

UpdateOneModel<Document> updateDoc = new UpdateOneModel<>(
Filters.eq("_id", 2),
Updates.set("age", 31));

有关本节中提到的方法和类的更多信息,请参阅以下资源

要执行删除操作,创建一个指定要删除的文档查询过滤器的 DeleteOneModelDeleteManyModel

DeleteOneModel 删除与查询过滤器匹配的第一个文档,而 DeleteManyModel 删除与查询过滤器匹配的所有文档。

重要

执行 bulkWrite() 时,如果查询过滤器没有匹配项,则 DeleteOneModelDeleteManyModel 不会删除任何文档。

以下示例创建了一个用于删除 _id1 的文档的 DeleteOneModel

DeleteOneModel<Document> deleteDoc = new DeleteOneModel<>(Filters.eq("_id", 1));

有关本节中提到的方法和类的更多信息,请参阅以下API文档:

bulkWrite() 方法接受一个可选的 BulkWriteOptions 作为第二个参数,用于指定批量操作的执行是按顺序还是无序。

默认情况下,bulkWrite() 方法按顺序执行批量操作。这意味着批量操作将按照你添加到列表中的顺序执行,直到发生错误(如果有)。

以下示例执行以下批量操作

  • 一个插入操作,插入一个具有 name 值为 "Zaynab Omar"age 值为 37 的文档

  • 一个替换操作,替换 _id1 的文档,该文档包含 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 }

您还可以通过在 BulkWriteOptionsorder() 方法中指定 "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 文档:InsertOneModelReplaceOneModelUpdateOneModelUpdateManyModelDeleteOneModelDeleteManyModel

执行 bulkWrite() 方法有两种方式

  • 有序,按顺序执行批量操作,直到发生错误(如果有任何错误发生)

  • 无序,按任何顺序执行所有批量操作,如果有错误发生,则在最后报告错误

返回

更新现有记录