Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

Migrar desde KMongo

Esta página contiene una comparación de alto nivel de la mayoría de las formas en que difieren el controlador oficial MongoDB Kotlin y el controlador desarrollado por la comunidad KMongo. Puedes utilizar esta página para identificar los cambios que necesitas realizar para migrar del controlador KMongo obsoleto al controlador oficial de MongoDB Kotlin.

KMongo es una popular librería desarrollada por la comunidad para trabajar con MongoDB desde aplicaciones en Kotlin. Es un contenedor alrededor del driver de Java que fue creado antes que el driver oficial de Kotlin para servir las necesidades de la Community de Kotlin.

Importante

A partir de julio de 2023, KMongo ha sido marcado como obsoleto.

El controlador MongoDB para Kotlin es el único controlador de MongoDB para Kotlin oficialmente soportado y mantenido. Es desarrollado por el equipo de MongoDB.

Aunque ambos controladores soportan operaciones síncronas y asíncronas, los ejemplos en esta página utilizarán operaciones asíncronas basadas en corutinas.

El controlador Kotlin es el controlador oficial de MongoDB para Kotlin. Está desarrollado por el equipo de MongoDB y proporciona una API nativa para que las aplicaciones Kotlin se conecten a MongoDB y trabajen con datos. Se implementa envolviendo el MongoDB Java driver.

KMongo es una popular librería desarrollada por la comunidad para trabajar con MongoDB desde aplicaciones en Kotlin. Es un contenedor alrededor del driver de Java que fue creado antes que el driver oficial de Kotlin para servir las necesidades de la Community de Kotlin.

Importante

A partir de julio de 2023, KMongo ha sido marcado como obsoleto.

El controlador de Kotlin se desarrolló en colaboración con el creador de KMongo, Julien Buret, para ofrecer a los usuarios un controlador respaldado oficialmente.

El controlador oficial de Kotlin y KMongo tienen APIs generalmente similares. Las similitudes notables entre el controlador de Kotlin y KMongo incluyen:

  • Soporte para operaciones síncronas y basadas en corrutinas

  • Soporte usando 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:

  • El driver oficial no tiene funcionalidad incorporada para reactor, rxjava2, Jackson, o GSON.

  • El driver oficial no admite comandos de shell de MongoDB.

Ambos drivers te permiten conectarte y comunicarte con clústeres de MongoDB desde una aplicación Kotlin.

Para conectar a un clúster de MongoDB utilizando el controlador de 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")

Ver el Conéctate a MongoDB documentación para más información.

Para conectarse a un clúster de MongoDB usando KMongo con corutinas:

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 MongoDB Kotlin Driver, KMongo permite inferir el nombre de la colección a partir del nombre de la clase de datos.

Ambos controladores proporcionan soporte para todas las API CRUD de MongoDB y operaciones de agregación.

Tip

Si estás acostumbrado a construir filtros de query utilizando la notación infija disponible en KMongo, también puedes usar esta notación para crear filtros en el driver oficial de Kotlin usando métodos de extensión de la mongodb-driver-kotlin-extensions paquete. Elija el Kotlin Driver Extensions pestaña para ver un ejemplo que usa esta sintaxis de query en el driver de Kotlin.

El MongoDB Kotlin Driver 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)

Puedes compilar pipelines de agregación usando 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) }

Consulta la documentación de Operaciones CRUD y Agregación para obtener más información.

Puedes usar la API de Builders de la biblioteca mongodb-driver-kotlin-extensions para crear filtros de query y etapas del pipeline de agregación directamente utilizando propiedades de clases de datos. Esta librería también permite crear queries usando 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 aprender más y ver ejemplos que usan todas las clases de desarrolladores, consulta la guía Usa Desarrolladores 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 construir pipelines de agregación usando 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, consulta la Descripción general de extensiones documentación de KMongo.

Ambos drivers brindan soporte para consultas de tipo seguro utilizando referencias de propiedad.

Tip

Si estás acostumbrado a construir filtros de query utilizando la notación infija disponible en KMongo, también puedes usar esta notación para crear filtros en el driver oficial de Kotlin usando métodos de extensión del paquete mongodb-driver-kotlin-extensions. Selecciona la pestaña Kotlin Driver Extensions para ver un ejemplo que utilice esta sintaxis de query en el driver de Kotlin.

El driver de MongoDB para Kotlin utiliza la API de desarrolladores para construir queries. Como alternativa, puedes 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 mapear una query de string de KMongo al driver de Kotlin, puedes usar la clase JsonObject.

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

Para más información, consulta la siguiente documentación del controlador de Kotlin:

Puedes utilizar la Builders API de la librería mongodb-driver-kotlin-extensions para construir consultas directamente en las propiedades de la clase de datos. Esta librería también permite crear queries usando 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 aprender más y ver ejemplos que usan todas las clases de desarrolladores, consulta la guía Usa Desarrolladores con Clases de Datos.

Con KMongo, puedes crear consultas mediante referencias de propiedades en la clase de datos que representa objetos en una colección y operadores infijos que proporciona la librería.

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 string de consultas que te permiten crear 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:

Ambos drivers 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 te 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 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")

Puedes 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")

Ambos controladores ofrecen soporte para serializar y deserializar objetos de datos en Kotlin hacia y desde BSON.

Puedes serializar las clases de datos en el driver de Kotlin utilizando tanto los códecs automáticos de clases de datos como la librería kotlinx.serialization. El controlador proporciona un eficiente Bson serializador que gestiona la serialización de objetos de Kotlin a datos 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
)

Para obtener más información, consulta la documentación de Kotlin Serialization.

Si usas la clase Document para representar tu colección, puedes serializarla a JSON y EJSON mediante 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 clase Document, consulta la documentación de Formato de datos de documentos - JSON extendido.

Puedes serializar datos en KMongo usando las siguientes librerías de serialización:

  • Jackson (por defecto)

  • 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)

Para obtener más información sobre los métodos de serialización de KMongo, consulta la documentación de KMongo sobre Mapeo de objetos.

Ambos controladores admiten operaciones síncronas y asíncronas.

El driver de MongoDB para Kotlin también tiene librerías separadas para operaciones síncronas y asíncronas. Sin embargo, el driver de Kotlin solo tiene funcionalidad incorporada para corrutinas como un paradigma asíncrono. El controlador de MongoDB Kotlin actualmente no proporciona soporte para otros paradigmas asíncronos, como Reactive Streams, Reactor o RxJava2.

Controlador
Paquete

sincronizar

com.mongodb.kotlin.client

corrutina

com.mongodb.kotlin.client.coroutine

A diferencia de KMongo, si deseas escribir código asíncrono, solo necesitas importar el paquete relevante.

Para escribir código síncrono:

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 corrutinas asíncronas:

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 librería principal org.litote.kmongo:kmongo con funcionalidades principales y librerías complementarias separadas que proporcionan soporte asincrónico a la librería principal.

KMongo admite los siguientes paradigmas asíncronos:

Estilo asíncrono
Paquete

reactive streams

org.litote.kmongo:kmongo-async

corrutina

com.mongodb.kotlin.client.coroutine and org.litote.kmongo.coroutine

Reactor

org.litote.kmongo:kmongo-reactor

RxJava2

org.litote.kmongo:kmongo-rxjava2

Para guardar 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 asíncrono de rutinas en Kotlin 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, consulta la Guía rápida en la documentación de KMongo.

Ahora que ha aprendido sobre las diferencias entre KMongo y el controlador MongoDB Kotlin, consulta la Guía de inicio rápido para comenzar a utilizar el controlador KMongo Kotlin.

Volver

Notas de versión

En esta página