从 KMongo 迁移
概述
此页面包含了对官方 MongoDB Kotlin 和社区开发的 KMongo 驱动程序之间大多数区别的概述比较。您可以使用此页面来识别从已弃用的 KMongo 驱动程序迁移到官方 MongoDB Kotlin 驱动程序所需的更改。
KMongo 是一个流行的由社区开发的库,用于从 Kotlin 应用程序中与 MongoDB 交互。它是在官方 Kotlin 驱动创建之前创建的 Java 驱动的包装器,旨在满足 Kotlin 社区的需求。
重要
截至 2023 年 7 月,KMongo 已被标记为弃用。
MongoDB Kotlin 驱动是官方支持和维护的 MongoDB 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 允许从数据类名称推断集合名称。
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 还支持字符串查询,允许您使用 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 集合中的数据。该 Document
类允许您以灵活的格式建模 MongoDB 集合中表示的数据。
您可以使用数据类和 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 的支持。
您可以使用 Kotlin 驱动程序使用自动数据类编解码器以及 kotlinx.serialization
库来序列化数据类。驱动程序提供了一个高效的 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
类来表示您的集合,您可以使用.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 编解码器引擎
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支持以下异步范式
异步样式 | 包 |
---|---|
Reactive Streams | org.litote.kmongo:kmongo-async |
协程 | com.mongodb.kotlin.client.coroutine 和 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 驱动。