Overview
Esta página contiene una comparación detallada de la mayoría de las diferencias entre el controlador oficial de MongoDB Kotlin y el controlador KMongo desarrollado por la comunidad. Puede usar esta página para identificar los cambios necesarios para migrar del controlador KMongo obsoleto al controlador oficial de MongoDB Kotlin.
KMongo es una popular biblioteca desarrollada por la comunidad para trabajar con MongoDB desde aplicaciones Kotlin. Es un contenedor del controlador de Java, creado antes de la creación del controlador oficial de Kotlin para satisfacer las necesidades de la comunidad Kotlin.
Importante
A partir del 2023 de julio, KMongo ha sido marcado como obsoleto.
El controlador MongoDB Kotlin es el controlador oficial para Kotlin, con soporte y mantenimiento. Está desarrollado por el equipo de MongoDB.
Aunque ambos controladores admiten operaciones sincrónicas y asincrónicas, los ejemplos de esta página utilizarán operaciones asincrónicas basadas en corrutinas.
Diferencias del controlador de Kotlin con KMongo
El controlador Kotlin es el controlador oficial de MongoDB para Kotlin. Desarrollado por el equipo de MongoDB, proporciona una API nativa para que las aplicaciones Kotlin se conecten a MongoDB y trabajen con datos. Se implementa encapsulando el controlador Java de MongoDB.
KMongo es una popular biblioteca desarrollada por la comunidad para trabajar con MongoDB desde aplicaciones Kotlin. Es un contenedor del controlador de Java, creado antes de la creación del controlador oficial de Kotlin para satisfacer las necesidades de la comunidad Kotlin.
Importante
A partir del 2023 de julio, KMongo ha sido marcado como obsoleto.
El controlador Kotlin se desarrolló en colaboración con el creador de KMongo, Julien Buret, para ofrecer a los usuarios un controlador con soporte oficial.
El controlador oficial de Kotlin y KMongo tienen APIs generalmente similares. Entre las similitudes más notables se incluyen:
Soporte para operaciones síncronas y basadas en corrutinas
Admite el uso de clases de datos para representar documentos MongoDB
Compatibilidad con la serialización de KotlinX
Compatibilidad con la API CRUD de MongoDB y la API de agregación
Aunque el controlador oficial de Kotlin y KMongo son similares, existen algunas diferencias clave:
Conectarse al clúster MongoDB
Ambos controladores le permiten conectarse y comunicarse con clústeres MongoDB desde una aplicación Kotlin.
Para conectarse a un clúster MongoDB usando el controlador MongoDB Kotlin:
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")
Vea el Conéctese a la documentación de MongoDB para obtener más información.
Para conectarse a un clúster MongoDB usando KMongo con corrutinas:
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>()
A diferencia del controlador Kotlin de MongoDB, KMongo permite inferir el nombre de la colección a partir del nombre de la clase de datos.
CRUD y agregación
Ambos controladores brindan soporte para todas las API CRUD y operaciones de agregación de MongoDB.
Tip
Si está acostumbrado a construir filtros de consulta mediante la notación infija disponible en KMongo, también puede usar esta notación para crear filtros en el controlador oficial de Kotlin mediante el uso de métodos de extensión de mongodb-driver-kotlin-extensions paquete. Seleccione el Kotlin Driver Extensions Pestaña para ver un ejemplo que utiliza esta sintaxis de consulta en el controlador Kotlin.
El controlador MongoDB Kotlin también proporciona funciones para todas las operaciones CRUD básicas:
// Insert a document val jedi = 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)
Puede crear canales de agregación utilizando el método aggregate() y la función 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) }
Consulte la documentación de Operaciones CRUD y agregación para obtener más información.
Puede usar la API de Builders de la biblioteca mongodb-driver-kotlin-extensions para crear filtros de consulta y etapas de agregación directamente mediante las propiedades de la clase de datos. Esta biblioteca también permite crear consultas mediante notación infija:
import com.mongodb.kotlin.client.model.Filters.eq import com.mongodb.kotlin.client.model.Filters.lt import com.mongodb.kotlin.client.model.Updates.set data class Jedi(val name: String, val age: Int) // Find documents val luke = collection.find(Jedi::name eq "Luke Skywalker") val jedis = collection.find(Jedi::age lt 30)).toList() // Update a document val filter = Jedi::name eq "Luke Skywalker" val update = Jedi::age.name set 20 collection.updateOne(filter, update) // Delete a document val filter = Jedi::name eq "Luke Skywalker" collection.deleteOne(filter)
Para obtener más información y ver ejemplos que utilizan todas las clases de generador, consulte la guía Usar generadores con clases de datos.
KMongo proporciona funciones para todas las operaciones CRUD básicas:
// 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")
Se pueden crear canalizaciones de agregación utilizando el método aggregate y la función pipeline:
val avgAge = collection.aggregate<Double>( pipeline( match(Jedi::name ne "Luke Skywalker"), group(Jedi::name, avg(Jedi::age)) ) ).toList()
Para obtener más información sobre los métodos disponibles, consulte la documentación de Descripción general de extensiones de KMongo.
Construir Consultas
Ambos controladores proporcionan soporte para consultas de tipos seguros utilizando referencias de propiedad.
Tip
Si está acostumbrado a construir filtros de consulta con la notación infija disponible en KMongo, también puede usar esta notación para crear filtros en el controlador oficial de Kotlin mediante los métodos de extensión del paquete mongodb-driver-kotlin-extensions. Seleccione la pestaña Kotlin Driver Extensions para ver un ejemplo que utiliza esta sintaxis de consulta en el controlador de Kotlin.
El controlador Kotlin de MongoDB utiliza la API Builders para crear consultas. También puede usar la clase 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)
Para asignar una consulta de cadena KMongo al controlador Kotlin, puede utilizar la clase JsonObject.
val query = JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}") val jsonResult = collection.find(query).firstOrNull()
Para obtener más información, consulte la siguiente documentación del controlador Kotlin:
Documentación de la API deJsonObject
Puede usar la API Builders de la biblioteca mongodb-driver-kotlin-extensions para crear consultas directamente sobre las propiedades de la clase de datos. Esta biblioteca también permite crear consultas mediante notación infija:
import com.mongodb.kotlin.client.model.Filters.eq import com.mongodb.kotlin.client.model.Filters.and import com.mongodb.kotlin.client.model.Filters.gt import com.mongodb.kotlin.client.model.Projections.excludeId import com.mongodb.kotlin.client.model.Projections.fields import com.mongodb.kotlin.client.model.Projections.include data class Person(val name: String, val gender: String, val age: Int) data class Result(val name: String) val collection = database.getCollection<Person>("people") // Infix Notation Query val filter = (Person::gender eq "female") and (Person::age gt 29)) val projection = fields(excludeId(), include(Person::name)) val results = collection.find<Result>(filter).projection(projection)
Para obtener más información y ver ejemplos que utilizan todas las clases de generador, consulte la guía Usar generadores con clases de datos.
Con KMongo, puede crear consultas utilizando referencias de propiedades en la clase de datos que representa objetos en una colección y operadores infijos que proporciona la biblioteca.
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 también admite consultas de cadena que le permiten construir consultas con el lenguaje de consulta 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()
Para obtener más información, consulte la siguiente documentación de KMongo:
Tipificación de datos
Ambos controladores admiten el uso de clases de datos de Kotlin y la clase Document para modelar los datos almacenados en una colección de MongoDB. La clase Document permite modelar los datos representados en una colección de MongoDB en un formato flexible.
Puede utilizar clases de datos y clases Document para modelar datos con el controlador Kotlin de MongoDB:
// 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")
Puede utilizar clases de datos y clases Document para modelar datos en 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")
Serialización de datos
Ambos controladores proporcionan soporte para serializar y deserializar objetos de datos en Kotlin hacia y desde BSON.
Puede serializar clases de datos en el controlador Kotlin utilizando códecs automáticos de clases de datos y la biblioteca kotlinx.serialization. El controlador proporciona un serializador Bson eficiente que gestiona la serialización de objetos Kotlin a datos 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 )
Para obtener más información, consulta la documentación de Kotlin Serialization.
Si usa la clase Document para representar su colección, puede serializarla en JSON y EJSON usando el método .toJson():
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)
Para obtener más información sobre la serialización de datos con la Document clase, consulte la documentación Formato de datos del documento - JSON extendido.
Puede serializar datos en KMongo utilizando las siguientes bibliotecas de serialización:
Jackson(por defecto)POJO Codec enginekotlinx.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)
Para obtener más información sobre los métodos de serialización de KMongo, consulte la documentación de Mapeo de objetos de KMongo.
Soporte sincrónico y asincrónico
Ambos controladores admiten operaciones sincrónicas y asincrónicas.
El controlador Kotlin de MongoDB también cuenta con bibliotecas independientes para operaciones síncronas y asíncronas. Sin embargo, solo admite corrutinas como paradigma asíncrono. Actualmente, no es compatible con otros paradigmas asíncronos como Reactive Streams, Reactor o RxJava2.
Controlador | Paquete |
|---|---|
Sincronizar | com.mongodb.kotlin.client |
Corrutinas | com.mongodb.kotlin.client.coroutine |
A diferencia de KMongo, si desea escribir código asincrónico, solo necesita importar el paquete relevante.
Para escribir código sincrónico:
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 = Jedi("Luke Skywalker", 19) collection.insertOne(jedi)
Para escribir código de corrutina asincrónica:
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 = Jedi("Luke Skywalker", 19) collection.insertOne(jedi) }
KMongo tiene una biblioteca central org.litote.kmongo:kmongo con funcionalidad principal y bibliotecas complementarias separadas que brindan soporte asincrónico a la biblioteca central.
KMongo admite los siguientes paradigmas asincrónicos:
Estilo asíncrono | Paquete |
|---|---|
Flujos reactivos | org.litote.kmongo:kmongo-async |
Corrutinas | com.mongodb.kotlin.client.coroutine and org.litote.kmongo.coroutine |
Reactor | org.litote.kmongo:kmongo-reactor |
RxJava2 | org.litote.kmongo:kmongo-rxjava2 |
Para escribir código sincrónico con 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")
Para escribir código de corrutina asincrónica con 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") }
Para obtener más información, consulte la Guía de inicio rápido en la documentación de KMongo.
¿Qué sigue?
Ahora que conoce las diferencias entre KMongo y el controlador MongoDB Kotlin, consulte la Guía de inicio rápido para comenzar a utilizar el controlador KMongo Kotlin.