Visão geral
Esta página contém uma comparação de alto nível da maioria das maneiras que o driver Kotlin oficial do MongoDB e o driver KMongo desenvolvido pela comunidade diferem. Você pode usar esta página para identificar as alterações que precisa fazer para migrar do driver KMongo obsoleto para o driver oficial Kotlin do MongoDB .
KMongo é uma biblioteca popular desenvolvida na comunidade para trabalhar com o MongoDB a partir de aplicativos Kotlin. É um invólucro em torno do driver Java que foi criado antes da criação do driver oficial do Kotlin para atender às necessidades da comunidade Kotlin.
Importante
A partir de julho de 2023, o KMongo foi marcado como obsoleto.
O driver Kotlin do MongoDB é o driver MongoDB oficialmente suportado e mantido para Kotlin. É desenvolvido pela equipe MongoDB.
Embora ambos os drivers ofereçam suporte a operações síncronas e assíncronas, os exemplos nesta página usarão operações assíncronas baseadas em coroutine.
Conectar ao MongoDB cluster
Ambos os drivers permitem que você se conecte e se comunique com clusters do MongoDB a partir de um aplicativo Kotlin.
Para se conectar a um cluster MongoDB usando o driver 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")
Consulte a documentação do Conectar ao MongoDB para mais informações.
Para se conectar a um cluster MongoDB usando o KMongo com corrotinas:
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>()
Ao contrário do MongoDB Kotlin Driver, o KMongo permite que o nome da coleção seja inferido a partir do nome da classe de dados.
CRUD e agregação
Ambos os drivers oferecem suporte para todas as API CRUD do MongoDB e operações de agregação.
Dica
Se você está familiarizado com a construção de filtros de query usando a notação infixa disponível no KMongo, também pode usar essa notação para criar filtros no driver oficial do Kotlin usando métodos de extensão do pacote mongodb-driver-kotlin-extensions
. Selecione a aba Kotlin Driver Extensions para visualizar um exemplo que utiliza esta sintaxe de consulta no driver Kotlin .
O driver Kotlin do MongoDB também fornece funções para todas as operações 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)
Você pode construir agregação pipelines utilizando o método aggregate()
e a função 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 a documentação de Operações e Agregação CRUD para obter mais informações.
Você pode usar a API de construtores da biblioteca mongodb-driver-kotlin-extensions
para criar filtros de consulta e estágios de pipeline de agregação diretamente usando propriedades da classe de dados. Esta biblioteca também permite criar queries usando notação infixa:
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 saber mais e visualizar exemplos que usam todas as classes de construtores, consulte o guia Usar construtores com classes de dados.
O KMongo fornece funções para todas as operações 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")
Os pipelines de agregação podem ser construídos utilizando o método aggregate
e a função pipeline
:
val avgAge = collection.aggregate<Double>( pipeline( match(Jedi::name ne "Luke Skywalker"), group(Jedi::name, avg(Jedi::age)) ) ).toList()
Para obter mais informações sobre os métodos disponíveis, consulte a Visão geral de extensões Documentação do KMongo.
Construa query
Ambos os drivers oferecem suporte a query seguras por tipo usando referências de propriedade.
Dica
Se você está familiarizado com a construção de filtros de query usando a notação infixa disponível no KMongo, também pode usar essa notação para criar filtros no driver oficial do Kotlin usando métodos de extensão do pacote mongodb-driver-kotlin-extensions
. Selecione a guia Kotlin Driver Extensions para visualizar um exemplo que usa essa sintaxe de consulta no driver Kotlin .
O driver Kotlin do MongoDB usa a API Builders para construir consultas. Alternativamente, você pode usar a classe 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 uma query de string KMongo para o driver Kotlin, você pode usar a classe JsonObject
.
val query = JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}") val jsonResult = collection.find(query).firstOrNull()
Para obter mais informações, consulte a seguinte documentação do driver Kotlin:
Guia de documentos
JsonObject Documentação da API
Você pode utilizar a API de Construtores da biblioteca do mongodb-driver-kotlin-extensions
para construir consultas diretamente nas propriedades da classe de dados. Esta biblioteca também permite criar queries usando notação infixa:
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 saber mais e visualizar exemplos que usam todas as classes de construtores, consulte o guia Usar construtores com classes de dados.
Com o KMongo, você pode criar queries usando referências de propriedade na classe de dados que representam objetos em uma coleção e operadores infixos que a biblioteca fornece.
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.*")
O KMongo também oferece suporte a queries de string que permitem construir queries com a linguagem de query do 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 obter mais informações, consulte a seguinte documentação do KMongo:
Digitação de dados
Ambos os drivers suportam o uso de classes de dados Kotlin e a classe Document
para modelar os dados armazenados em uma coleção MongoDB . A classe Document
permite modelar dados representados em uma coleção MongoDB em um formato flexível.
Você pode usar classes de dados e classes Document
para modelar dados com o MongoDB Kotlin Driver:
// 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")
Você pode usar classes de dados e classes Document
para modelar dados no 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")
serialização de dados
Ambos os drivers fornecem suporte para serializar e desserializar objetos de dados no Kotlin de e para o BSON.
Você pode serializar classes de dados no driver Kotlin usando codecs de classe de dados automáticos e a biblioteca kotlinx.serialization
. O driver fornece um serializador Bson
eficiente que lida com a serialização de objetos Kotlin para dados 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 saber mais, consulte a documentação de serialização do Kotlin .
Se você utilizar a classe Document
para representar sua collection, você poderá serializá-la para JSON e EJSON utilizando o 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 saber mais sobre a serialização de dados com a classe Document
, consulte Formato de dados do documento - documentação JSON estendida .
Você pode serializar dados no KMongo usando as seguintes bibliotecas de serialização:
Jackson
(padrão)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)
Para saber mais sobre os métodos de serialização do KMongo, consulte Mapeamento de objetos Documentação do KMongo.
Suporte síncrono e assíncrono
Ambos os drivers suportam operações síncronas e assíncronas.
O driver Kotlin do MongoDB também possui bibliotecas separadas para operações síncronas e assíncronas. No entanto, o driver Kotlin só tem suporte integrado para corrotinas como um paradigma assíncrono. Atualmente, o driver Kotlin do MongoDB não oferece suporte para outros paradigmas assíncronos, como Reactive Streams, Reactor ou RxJava2.
Driver | Pacote |
---|---|
sincronizar | com.mongodb.kotlin.client |
Coroutines | com.mongodb.kotlin.client.coroutine |
Diferentemente do KMongo, se você quiser escrever código assíncrono, só precisará importar o pacote relevante.
Para escrever 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 escrever código corrotina assíncrono:
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) }
O KMongo tem uma biblioteca principal org.litote.kmongo:kmongo
com funcionalidade principal e bibliotecas complementares separadas que fornecem suporte assíncrono à biblioteca principal.
O KMongo suporta os seguintes paradigmas assíncronos:
Estilo assíncrono | Pacote |
---|---|
reactive streams | org.litote.kmongo:kmongo-async |
Coroutines | com.mongodb.kotlin.client.coroutine and org.litote.kmongo.coroutine |
Reator | org.litote.kmongo:kmongo-reactor |
RxJava2 | org.litote.kmongo:kmongo-rxjava2 |
Para escrever código síncrono com 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 escrever código coroutine assíncrono com 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 saber mais, consulte o Início Rápido na documentação do KMongo.
E agora?
Agora que você leu as diferenças entre o KMongo e o driver MongoDB Kotlin, consulte o Início rápido para começar a usar o driver KMongo Kotlin.