Docs 菜单
Docs 主页
/ / /
Kotlin 协程
/ / /

批量操作

在此页面上

  • Overview
  • 执行批量操作
  • 插入操作
  • 替换操作
  • 更新操作
  • 删除操作
  • 执行顺序
  • 命令执行
  • 无序执行
  • 总结

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

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

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

批量操作由大量写入操作组成。 要执行批量操作,请将包含WriteModel文档的List传递给bulkWrite()方法。 WriteModel是表示单个写入操作的模型。

以下部分介绍如何创建和使用WriteModel类型的每个变体。 每节中的示例都使用peoplecollection中的以下文档:

{ "_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无法插入collection中已存在的具有_id的文档。 在这种情况下,驱动程序会抛出一个MongoBulkWriteException

以下示例尝试插入两个文档,其中_id值为13 。由于collection中已存在_id1的文档,因此该操作会导致错误:

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

要了解驱动程序为何未插入_id3的文档,请参阅“执行顺序”部分。

有关本节提及的方法和类的详情,请参阅 InsertOneModel API 文档。

要执行替换操作,请创建ReplaceOneModel ,为要替换的文档和替换文档指定查询筛选器。

重要

执行bulkWrite()时, ReplaceOneModel不能进行违反collection上唯一索引约束的更改。此外,如果查询筛选器没有匹配项,则模型不会执行替换操作。

以下示例创建了一个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类型不能进行违反collection唯一索引约束的更改。此外,如果没有与查询筛选器的匹配项,则模型不会执行更新操作。

以下示例在UpdateOneModel age1 的文档中创建一个 ,以使 字段递增_id 2

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类型不会删除任何文档。

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

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

有关本节中提到的方法和类的详情,请参阅以下 API 文档:

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

默认情况下, bulkWrite()方法按顺序执行批量操作。 这意味着,这些操作会按照您添加到列表中的顺序执行,直到出现任何错误。

以下示例执行这些批量操作:

  • 针对name"Zaynab Omar"age37的文档的插入操作

  • _id1的文档替换为包含location字段的新文档的替换操作

  • 针对_id6的文档的更新操作,用于更改name字段

  • 针对age值大于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()方法在更新操作后执行插入操作,则更新操作不会产生更改,因为该文档当时不存在。该collection将包含以下文档:

{ "_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() 方法:

  • 有序,驱动程序按顺序执行写入操作,直到出现错误

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

后退

在单个操作中插入或更新