文档菜单
文档首页
/ / /
Kotlin 协程

批量操作

本页

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

在本指南中,您可以了解如何在MongoDB Kotlin驱动程序中使用批量操作。

对于单个CRUD操作,您可以使用相关方法。例如,要插入一个文档然后更新多个文档,您可以使用insertOne()方法和updateMany()方法。

MongoClient通过向每个操作对应的数据库发起请求来执行这些操作。您可以通过使用批量操作来减少对数据库的调用次数。

批量操作由大量写操作组成。要执行批量操作,将包含WriteModel文档的List传递给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 }

此数据使用以下Kotlin数据类进行建模

data class Person(
@BsonId val id: Int,
val name: String,
val age: Int? = null,
val location: String? = null
)

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

  • bulkWrite()

  • WriteModel

  • BulkWriteOptions

要执行插入操作,创建一个指定要插入的文档的InsertOneModel。要插入多个文档,必须为要插入的每个文档创建一个InsertOneModel

以下示例创建了一个描述人员的两个文档的InsertOneModel

val juneDoc = InsertOneModel(Person(3, "June Carrie", 17))
val kevinDoc = InsertOneModel(Person(4, "Kevin Moss", 22))

重要

当执行bulkWrite()操作时,InsertOneModel不能插入一个在集合中已经存在的_id的文档。在这种情况下,驱动程序会抛出MongoBulkWriteException

以下示例尝试插入两个文档,其中_id的值为1和3。由于集合中已经存在一个_id为1的文档,操作结果为错误

try {
val bulkOperations = listOf(
(InsertOneModel(Person(1, "James Smith", 13))),
(InsertOneModel(Person(3, "Colin Samuels")))
)
val bulkWrite = collection.bulkWrite(bulkOperations)
} catch (e: MongoBulkWriteException) {
println("A MongoBulkWriteException occurred with the following message: " + e.message)
}
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 来替换 _id1 的文档,该文档包含额外的 location 字段

val filter = Filters.eq("_id", 1)
val insert = Person(1, "Celine Stork", location = "San Diego, CA")
val doc = ReplaceOneModel(filter, insert)

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

要执行更新操作,创建一个指定查询过滤器和更新文档的 UpdateOneModelUpdateManyModel

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

重要

在执行 bulkWrite() 时,UpdateOneModelUpdateManyModel 类型不能执行违反集合唯一索引约束的更改。此外,如果没有匹配到查询过滤器,这些模型不会执行更新操作。

以下示例创建了一个UpdateOneModel来增加文档中age字段1,该文档的_id2

val filter = Filters.eq("_id", 2)
val update = Updates.inc(Person::age.name, 1)
val doc = UpdateOneModel<Person>(filter, update)

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

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

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

重要

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

以下示例创建了一个用于删除_id1的文档的DeleteOneModel,以及一个用于删除age值小于30的文档的DeleteManyModel

val deleteId1 = DeleteOneModel<Person>(Filters.eq("_id", 1))
val deleteAgeLt30 = DeleteManyModel<Person>(Filters.lt(Person::age.name, 30))

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

默认情况下,bulkWrite()方法以顺序执行批量操作。这意味着操作将在你将其添加到列表中的顺序执行,直到发生任何错误。

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

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

  • 一个插入操作,其中文档的 name"Zaynab Omar",且 age37

  • 一个替换操作,其中文档的 _id1,替换为包含 location 字段的文档

  • 一个更新操作,其中文档的 _id6,以更改 name 字段

  • 一个删除操作,删除所有年龄大于 50 的文档

val insertMdl = InsertOneModel(Person(6, "Zaynab Omar", 37))
val replaceMdl = ReplaceOneModel(
Filters.eq("_id", 1),
Person(1, "Sandy Kane", location = "Helena, MT")
)
val updateMdl = UpdateOneModel<Person>(
Filters.eq("_id", 6),
Updates.set(Person::name.name, "Zaynab Hassan")
)
val deleteMdl = DeleteManyModel<Person>(Filters.gt(Person::age.name, 50))
val bulkOperations = listOf(
insertMdl,
replaceMdl,
updateMdl,
deleteMdl
)
val result = 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 }

您也可以通过将 false 传递给 BulkWriteOptions 对象上的 ordered() 方法来以任何顺序执行批量操作。这意味着所有写操作都会执行,无论是否有错误。如果发生错误,驱动程序将在最后报告。

以下代码显示了如何执行无序执行的批量操作

val options = BulkWriteOptions().ordered(false)
val unorderedResult = 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()方法。

WriteModel有六种变体

  • InsertOneModel

  • ReplaceOneModel

  • UpdateOneModel

  • UpdateManyModel

  • DeleteOneModel

  • DeleteManyModel

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

  • 有序,驱动程序将按顺序执行写操作,直到发生任何错误

  • 无序,驱动程序以任何顺序执行所有写操作,并在操作完成后报告任何错误

下一步

MongoDB Kotlin 驱动程序