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

从 KMongo 迁移

在此页面上

  • Overview
  • 连接到 MongoDB cluster
  • CRUD 和聚合
  • 构建查询
  • 数据类型
  • 数据序列化
  • 同步和异步支持
  • 下一步

本页面对官方 MongoDB Kotlin 和社区开发的 KMongo 驱动程序的大多数不同之处进行了高级比较。 您可以使用此页面来确定从已弃用的 KMongo 驱动程序迁移到官方 MongoDB Kotlin 驱动程序时需要进行的更改。

KMongo 是一个由社区开发的流行库,用于从 Kotlin 应用程序使用 MongoDB。它是 Java 驱动程序的包装器,在创建官方 Kotlin 驱动程序之前创建,以满足 Kotlin 社区的需求。

重要

自 2023 年 7 月起,KMongo 已被标记为已弃用。

MongoDB Kotlin 驱动程序是官方支持和维护的适用于 Kotlin 的 MongoDB 驱动程序。它由 MongoDB 团队开发。

尽管这两个驱动程序都支持同步和异步操作,但本页上的示例将使用基于异步协程的操作。

这两个驱动程序都允许您从 Kotlin 应用程序连接到 MongoDB 集群并与之通信。

要使用 MongoDB Kotlin 驱动程序连接到 MongoDB 集群,请执行以下操作:

import com.mongodb.kotlin.client.coroutine.MongoClient
data class Jedi(val name: String, val age: Int)
// Replace the placeholder with your MongoDB deployment's connection string
val uri = CONNECTION_STRING_URI_PLACEHOLDER
val mongoClient = MongoClient.create(uri)
val database = mongoClient.getDatabase("test")
// Get a collection of documents of type Jedi
val collection = database.getCollection<Jedi>("jedi")

有关更多信息,请参阅连接到MongoDB文档。

要使用带有协程的 KMongo 连接到MongoDB 集群,请执行以下操作:

import org.litote.kmongo.reactivestreams.*
import org.litote.kmongo.coroutine.*
data class Jedi(val name: String, val age: Int)
// Get new MongoClient instance using coroutine extension
val client = KMongo.createClient().coroutine
val database = client.getDatabase("test")
// Get a collection of documents of type Jedi
val col = database.getCollection<Jedi>()

与MongoDB Kotlin驾驶员不同,KMongo 允许从数据类名称推断集合名称。

这两个驱动程序都支持所有 MongoDB CRUD API 和聚合操作。

MongoDB Kotlin 驱动程序还为所有基本 CRUD 操作提供函数:

// Insert a document
val jedi =a Jedi("Luke Skywalker", 19)
collection.insertOne(jedi)
// Find a document
val luke = collection.find(Jedi::name.name, "Luke Skywalker")
val jedis = collection.find(lt(Jedi::age.name, 30)).toList()
// Update a document
val filter = Filters.eq(Jedi::name.name, "Luke Skywalker")
val update = Updates.set(Jedi::age.name, 20)
collection.updateOne(filter, update)
// Delete a document
val filter = Filters.eq(Jedi::name.name, "Luke Skywalker")
collection.deleteOne(filter)

可以使用 aggregate方法和pipeline函数构建聚合管道:

data class Results(val avgAge: Double)
val resultsFlow = collection.aggregate<Results>(
listOf(
Aggregates.match(Filters.ne(Jedi::name.name, "Luke Skywalker")),
Aggregates.group("\$${Jedi::name.name}",
Accumulators.avg("avgAge", "\$${Jedi::age.name}"))
)
)
resultsFlow.collect { println(it) }

有关更多信息,请参阅CRUD聚合文档。

KMongo 为所有基本CRUD操作提供了函数:

// Insert a document
val jedi = Jedi("Luke Skywalker", 19)
col.insertOne(jedi)
// Find a document
val luke = col.findOne(Jedi::name eq "Luke Skywalker")
val jedis = col.find(Jedi::age lt 30).toList()
// Update a document
col.updateOne(Jedi::name eq "Luke Skywalker", setValue(Jedi::age, 20))
// Delete a document
col.deleteOne(Jedi::name eq "Luke Skywalker")

可以使用aggregate方法和pipeline函数构建聚合管道:

val avgAge = collection.aggregate<Double>(
pipeline(
match(Jedi::name ne "Luke Skywalker"),
group(Jedi::name, avg(Jedi::age))
)
).toList()

有关可用方法的更多信息,请参阅 扩展概述 KMongo 文档。

这两个驱动程序都支持使用属性引用的类型安全查询。

MongoDB Kotlin 驱动程序使用 Builders API 来构造查询。 或者,您可以使用Document类。

data class Person(val name: String, val email: String, val gender: String, val age: Int)
data class Results(val email: String)
val collection = database.getCollection<Person>("people")
// Using Builders
val filter = and(eq("gender", "female"), gt("age", 29))
val projection = fields(excludeId(), include("email"))
val results = collection.find<Results>(filter).projection(projection)
// Using Document class
val filter = Document().append("gender", "female").append("age", Document().append("\$gt", 29))
val projection = Document().append("_id", 0).append("email", 1)
val results = collection.find<Results>(filter).projection(projection)

要将 KMongo 字符串查询映射到 Kotlin 驱动程序,您可以使用JsonObject类。

val query = JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}")
val jsonResult = collection.find(query).firstOrNull()

有关更多信息,请参阅以下 Kotlin 驱动程序文档:

  • 构建器

  • 文档指南

  • JsonObject API 文档

借助 KMongo,您可以使用对表示集合中对象的数据类的属性引用以及库提供的中缀运算符来创建查询。

data class Jedi(val name: String)
val yoda = col.findOne(Jedi::name eq "Yoda")
// Compile error (2 is not a String)
val error = col.findOne(Jedi::name eq 2)
// Use property reference with instances
val yoda2 = col.findOne(yoda::name regex "Yo.*")

KMongo 还支持string查询,可让您使用MongoDB查询语言构建查询:

import org.litote.kmongo.MongoOperator.lt
import org.litote.kmongo.MongoOperator.match
import org.litote.kmongo.MongoOperator.regex
import org.litote.kmongo.MongoOperator.sample
val yoda = col.findOne("{name: {$regex: 'Yo.*'}}")!!
val luke = col.aggregate<Jedi>("""[ {$match:{age:{$lt : ${yoda.age}}}},
{$sample:{size:1}}
]""").first()

有关更多信息,请参阅以下 KMongo 文档:

这两个驱动程序都支持使用 Kotlin 数据类和Document类对存储在 MongoDB collection中的数据进行建模。Document类允许您以灵活的格式对 MongoDB collection中表示的数据进行建模。

您可以使用数据类和Document类,通过 MongoDB Kotlin 驱动程序对数据进行建模:

// With data class
data class Movie(val title: String, val year: Int, val rating: Float)
val dataClassCollection = database.getCollection<Movie>("movies")
val movieDataClass = dataClassCollection.findOneOrNull()
val movieNameDataClass = movieDataClass.title
// With Document class
val documentCollection = database.getCollection<Movie>("movies")
val movieDocument = documentCollection.findOneOrNull()
val movieTitleDocument = movieDocument.getString("title")

您可以使用数据类和Document类在 KMongo 中对数据进行建模:

// With data class
data class Movie(val title: String, val year: Int, val rating: Float)
val collection = database.getCollection<Movie>("movies")
val movieDataClass = dataClassCollection.findOne()
val movieNameDataClass = movieDataClass.title
// With Document class
val documentCollection = database.getCollection("movies")
val movieDocument = documentCollection.findOne()
val movieTitleDocument = movieDocument.getString("title")

这两个驱动程序都支持在 Kotlin 中将数据对象与 BSON 进行序列化和反序列化。

您可以使用自动数据类编解码器和kotlinx.serialization库在 Kotlin 驱动程序中序列化数据类。 该驱动程序提供了一个高效的Bson序列化器,用于处理 Kotlin 对象到 BSON 数据的序列化。

@Serializable
data class LightSaber(
@SerialName("_id") // Use instead of @BsonId
@Contextual val id: ObjectId?,
val color: String,
val qty: Int,
@SerialName("brand")
val manufacturer: String = "Acme" // Use instead of @BsonProperty
)

要了解更多信息,请参阅Kotlin 序列化文档。

如果使用Document类表示collection,则可以使用.toJson()方法将其序列化为 JSON 和 EJSON:

val document = Document("_id", 1).append("color", "blue")
// Serialize to JSON
document.toJson()
// Serialize to EJSON
val settings = JsonWriterSettings.builder().outputMode(JsonMode.STRICT).build()
val json = doc.toJson(settings)

要了解有关使用Document类序列化数据的更多信息,请参阅文档数据格式 - 扩展 JSON文档。

您可以使用以下序列化库在 KMongo 中序列化数据:

  • Jackson (默认)

  • POJO Codec engine

  • kotlinx.serialization

// Using KotlinX Serialization
@Serializable
data class Data(@Contextual val _id: Id<Data> = newId())
val json = Json { serializersModule = IdKotlinXSerializationModule }
val data = Data()
val json = json.encodeToString(data)

要学习;了解有关 KMongo 序列化方法的更多信息,请参阅 对象映射 KMongo 文档。

这两个驱动程序都支持同步和异步操作。

MongoDB Kotlin 驱动程序还具有用于同步和异步操作的单独库。 但是,Kotlin 驱动程序仅内置支持将协程作为异步范例。 MongoDB Kotlin 驱动程序目前不支持其他异步范例,例如 Reactive Streams、Reactor 或 RxJava2。

驱动
安装包
同步
com.mongodb.kotlin.client
协程
com.mongodb.kotlin.client.coroutine

与 KMongo 不同,如果要编写异步代码,只需导入相关包即可。

要编写同步代码:

import com.mongodb.kotlin.client.MongoClient
// Instantiate your collection
data class Jedi(val name: String, val age: Int)
val uri = "<your-connection-string">
val mongoClient = MongoClient.create(uri)
val database = mongoClient.getDatabase("test")
val collection = database.getCollection<Jedi>("jedi")
// Synchronous operations
val jedi =a Jedi("Luke Skywalker", 19)
collection.insertOne(jedi)

要编写异步协程代码,请执行以下操作:

import com.mongodb.kotlin.client.coroutine.MongoClient
// Instantiate your collection
data class Jedi(val name: String, val age: Int)
val uri = "<your-connection-string">
val mongoClient = MongoClient.create(uri)
val database = mongoClient.getDatabase("test")
val collection = database.getCollection<Jedi>("jedi")
runBlocking {
// Async operations
val jedi =a Jedi("Luke Skywalker", 19)
collection.insertOne(jedi)
}

KMongo 有一个具有主要功能的核心库org.litote.kmongo:kmongo和为核心库提供异步支持的独立伴随库。

KMongo 支持以下异步范例:

异步样式
安装包
反应流
org.litote.kmongo:kmongo-async
协程
com.mongodb.kotlin.client.coroutine and org.litote.kmongo.coroutine
Reactor
org.litote.kmongo:kmongo-reactor
RxJava2
org.litote.kmongo:kmongo-rxjava2

要使用 KMongo写入同步代码,请执行以下操作:

import org.litote.kmongo.*
// Instantiate your collection
data class Jedi(val name: String, val age: Int)
val client = KMongo.createClient()
val database = client.getDatabase("test")
val col = database.getCollection<Jedi>()
// Synchronous operations
col.insertOne(Jedi("Luke Skywalker", 19))
val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda")

要使用 KMongo 编写异步协程代码:

import org.litote.kmongo.reactivestreams.*
import org.litote.kmongo.coroutine.*
// Instantiate your collection
data class Jedi(val name: String, val age: Int)
val client = KMongo.createClient()
val database = client.getDatabase("test")
val col = database.getCollection<Jedi>()
runBlocking {
// Async operations
col.insertOne(Jedi("Luke Skywalker", 19))
val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda")
}

要学习;了解更多信息,请参阅 快速入门 在 KMongo 文档中。

现在您已经了解了 KMongo 和 MongoDB Kotlin 驱动程序之间的区别,请参阅快速入门以开始使用 KMongo Kotlin 驱动程序。

后退

兼容性