从 KMongo 迁移
Overview
本页面对官方 MongoDB Kotlin 和社区开发的 KMongo 驱动程序的大多数不同之处进行了高级比较。 您可以使用此页面来确定从已弃用的 KMongo 驱动程序迁移到官方 MongoDB Kotlin 驱动程序时需要进行的更改。
KMongo 是一个由社区开发的流行库,用于从 Kotlin 应用程序使用 MongoDB。它是 Java 驱动程序的包装器,在创建官方 Kotlin 驱动程序之前创建,以满足 Kotlin 社区的需求。
重要
自 2023 年 7 月起,KMongo 已被标记为已弃用。
MongoDB Kotlin 驱动程序是官方支持和维护的适用于 Kotlin 的 MongoDB 驱动程序。它由 MongoDB 团队开发。
尽管这两个驱动程序都支持同步和异步操作,但本页上的示例将使用基于异步协程的操作。
连接到 MongoDB cluster
这两个驱动程序都允许您从 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 允许从数据类名称推断集合名称。
CRUD 和聚合
这两个驱动程序都支持所有 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) }
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 数据的序列化。
data class LightSaber( // Use instead of @BsonId val id: ObjectId?, val color: String, val qty: Int, 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 data class Data( 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 驱动程序。