This page contains a high-level comparison of most of the ways the official MongoDB Kotlin Driver and the community-developed KMongo driver differ. You can use this page to identify the changes you need to make to migrate from the deprecated KMongo driver to the official MongoDB Kotlin Driver.
KMongo is a popular community-developed library for working with MongoDB from Kotlin applications. It is a wrapper around the Java driver that was created prior to the creation of the official Kotlin driver to serve the needs of the Kotlin community.
ImportantAs of July 2023, KMongo has been marked as deprecated.
The MongoDB Kotlin Driver is the officially supported and maintained MongoDB driver for Kotlin. It is developed by the MongoDB team.
Although both drivers support synchronous and asynchronous operations, the examples on this page will use asynchronous coroutine-based operations.
Both drivers let you connect to and communicate with MongoDB clusters from a Kotlin application.
To connect to a MongoDB cluster using the MongoDB Kotlin Driver:
import com.mongodb.kotlin.client.coroutine.MongoClientdata class Jedi(val name: String, val age: Int)val uri = CONNECTION_STRING_URI_PLACEHOLDERval mongoClient = MongoClient.create(uri)val database = mongoClient.getDatabase("test")val collection = database.getCollection<Jedi>("jedi")
See the Connect to MongoDB documentation for more information.
To connect to a MongoDB cluster using KMongo with coroutines:
import org.litote.kmongo.reactivestreams.*import org.litote.kmongo.coroutine.*data class Jedi(val name: String, val age: Int)val client = KMongo.createClient().coroutineval database = client.getDatabase("test")val col = database.getCollection<Jedi>()
Unlike the MongoDB Kotlin Driver, KMongo allows the collection name to be inferred from the data class name.
Both drivers provide support for all MongoDB CRUD APIs and aggregation operations.
TipIf you are accustomed to constructing query filters by using the infix notation available in KMongo, you can also use this notation to create filters in the official Kotlin driver by using extension methods from the mongodb-driver-kotlin-extensions
package. Select the Kotlin Driver Extensions tab to view an example that uses this query syntax in the Kotlin driver.
The MongoDB Kotlin Driver also provides functions for all basic CRUD operations:
val jedi = Jedi("Luke Skywalker", 19)collection.insertOne(jedi)val luke = collection.find(Jedi::name.name, "Luke Skywalker")val jedis = collection.find(lt(Jedi::age.name, 30)).toList()val filter = Filters.eq(Jedi::name.name, "Luke Skywalker")val update = Updates.set(Jedi::age.name, 20)collection.updateOne(filter, update)val filter = Filters.eq(Jedi::name.name, "Luke Skywalker")collection.deleteOne(filter)
You can build aggregation pipelines by using the aggregate()
method and the pipeline
function:
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) }
See the CRUD Operations and Aggregation documentation for more information.
You can use the Builders API from the mongodb-driver-kotlin-extensions
library to create query filters and aggregation pipeline stages directly using data class properties. This library also allows you to create queries by using infix notation:
import com.mongodb.kotlin.client.model.Filters.eqimport com.mongodb.kotlin.client.model.Filters.ltimport com.mongodb.kotlin.client.model.Updates.setdata class Jedi(val name: String, val age: Int)val luke = collection.find(Jedi::name eq "Luke Skywalker")val jedis = collection.find(Jedi::age lt 30)).toList()val filter = Jedi::name eq "Luke Skywalker"val update = Jedi::age.name set 20collection.updateOne(filter, update)val filter = Jedi::name eq "Luke Skywalker"collection.deleteOne(filter)
To learn more and view examples that use all the builder classes, see the Use Builders with Data Classes guide.
KMongo provides functions for all basic CRUD operations:
val jedi = Jedi("Luke Skywalker", 19)col.insertOne(jedi)val luke = col.findOne(Jedi::name eq "Luke Skywalker")val jedis = col.find(Jedi::age lt 30).toList()col.updateOne(Jedi::name eq "Luke Skywalker", setValue(Jedi::age, 20))col.deleteOne(Jedi::name eq "Luke Skywalker")
Aggregation pipelines can be built using the aggregate
method and the pipeline
function:
val avgAge = collection.aggregate<Double>( pipeline( match(Jedi::name ne "Luke Skywalker"), group(Jedi::name, avg(Jedi::age)) )).toList()
For more information on available methods, see the Extensions Overview KMongo documentation.
Both drivers provide support for type-safe queries using property references.
TipIf you are accustomed to constructing query filters by using the infix notation available in KMongo, you can also use this notation to create filters in the official Kotlin driver by using extension methods from the mongodb-driver-kotlin-extensions
package. Select the Kotlin Driver Extensions tab to view an example that uses this query syntax in the Kotlin driver.
The MongoDB Kotlin Driver uses the Builders API to construct queries. Alternatively, you can use the Document
class.
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")val filter = and(eq("gender", "female"), gt("age", 29))val projection = fields(excludeId(), include("email"))val results = collection.find<Results>(filter).projection(projection)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)
To map a KMongo string query to the Kotlin driver, you can use the JsonObject
class.
val query = JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}")val jsonResult = collection.find(query).firstOrNull()
For more information, see the following Kotlin driver documentation:
Documents guide
JsonObject API Documentation
You can use the Builders API from the mongodb-driver-kotlin-extensions
library to construct queries directly on data class properties. This library also allows you to create queries by using infix notation:
import com.mongodb.kotlin.client.model.Filters.eqimport com.mongodb.kotlin.client.model.Filters.andimport com.mongodb.kotlin.client.model.Filters.gtimport com.mongodb.kotlin.client.model.Projections.excludeIdimport com.mongodb.kotlin.client.model.Projections.fieldsimport com.mongodb.kotlin.client.model.Projections.includedata class Person(val name: String, val gender: String, val age: Int)data class Result(val name: String)val collection = database.getCollection<Person>("people")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)
To learn more and view examples that use all the builder classes, see the Use Builders with Data Classes guide.
With KMongo, you can create queries using property references on the data class that represents objects in a collection and infix operators that the library provides.
data class Jedi(val name: String)val yoda = col.findOne(Jedi::name eq "Yoda")val error = col.findOne(Jedi::name eq 2)val yoda2 = col.findOne(yoda::name regex "Yo.*")
KMongo also supports string queries that let you construct queries with MongoDB Query Language:
import org.litote.kmongo.MongoOperator.ltimport org.litote.kmongo.MongoOperator.matchimport org.litote.kmongo.MongoOperator.regeximport org.litote.kmongo.MongoOperator.sampleval yoda = col.findOne("{name: {$regex: 'Yo.*'}}")!!val luke = col.aggregate<Jedi>("""[ {$match:{age:{$lt : ${yoda.age}}}}, {$sample:{size:1}} ]""").first()
For more information, see the following KMongo documentation:
Both drivers support the use of Kotlin data classes and the Document
class to model the data stored in a MongoDB collection. The Document
class lets you model data represented in a MongoDB collection in a flexible format.
You can use data classes and Document
classes to model data with the MongoDB Kotlin Driver:
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.titleval documentCollection = database.getCollection<Movie>("movies")val movieDocument = documentCollection.findOneOrNull()val movieTitleDocument = movieDocument.getString("title")
You can use data classes and Document
classes to model data in KMongo:
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.titleval documentCollection = database.getCollection("movies")val movieDocument = documentCollection.findOne()val movieTitleDocument = movieDocument.getString("title")
Both drivers provide support for serializing and deserializing data objects in Kotlin to and from BSON.
You can serialize data classes in the Kotlin driver using both automatic data class codecs and the kotlinx.serialization
library. The driver provides an efficient Bson
serializer that handles the serialization of Kotlin objects to BSON data.
@Serializabledata class LightSaber( @SerialName("_id") @Contextual val id: ObjectId?, val color: String, val qty: Int, @SerialName("brand") val manufacturer: String = "Acme" )
To learn more, see the Kotlin Serialization documentation.
If you use the Document
class to represent your collection, you can serialize it to JSON and EJSON using the .toJson()
method:
val document = Document("_id", 1).append("color", "blue")document.toJson()val settings = JsonWriterSettings.builder().outputMode(JsonMode.STRICT).build()val json = doc.toJson(settings)
To learn more about serializing data with the Document
class, refer to Document Data Format - Extended JSON documentation.
You can serialize data in KMongo using the following serialization libraries:
Jackson
(default)
POJO Codec engine
kotlinx.serialization
@Serializabledata class Data(@Contextual val _id: Id<Data> = newId())val json = Json { serializersModule = IdKotlinXSerializationModule }val data = Data()val json = json.encodeToString(data)
To learn more about the KMongo serialization methods, refer to the Object Mapping KMongo documentation.
Both drivers support synchronous and asynchronous operations.
The MongoDB Kotlin Driver also has separate libraries for synchronous and asynchronous operations. However, the Kotlin driver only has built-in support for coroutines as an asynchronous paradigm. The MongoDB Kotlin Driver does not currently provide support for other asynchronous paradigms such as Reactive Streams, Reactor, or RxJava2.
Driver
Package
Sync
com.mongodb.kotlin.client
Coroutines
com.mongodb.kotlin.client.coroutine
Unlike KMongo, if you want to write asynchronous code, you only need to import the relevant package.
To write synchronous code:
import com.mongodb.kotlin.client.MongoClientdata 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")val jedi = Jedi("Luke Skywalker", 19)collection.insertOne(jedi)
To write asynchronous coroutine code:
import com.mongodb.kotlin.client.coroutine.MongoClientdata 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 { val jedi = Jedi("Luke Skywalker", 19) collection.insertOne(jedi)}
KMongo has a core library org.litote.kmongo:kmongo
with main functionality and separate companion libraries that provide asynchronous support to the core library.
KMongo supports the following asynchronous paradigms:
Async Style
Package
Reactive Streams
org.litote.kmongo:kmongo-async
Coroutines
com.mongodb.kotlin.client.coroutine
and org.litote.kmongo.coroutine
Reactor
org.litote.kmongo:kmongo-reactor
RxJava2
org.litote.kmongo:kmongo-rxjava2
To write synchronous code with KMongo:
import org.litote.kmongo.*data class Jedi(val name: String, val age: Int)val client = KMongo.createClient()val database = client.getDatabase("test")val col = database.getCollection<Jedi>()col.insertOne(Jedi("Luke Skywalker", 19))val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda")
To write async coroutine code with KMongo:
import org.litote.kmongo.reactivestreams.*import org.litote.kmongo.coroutine.*data class Jedi(val name: String, val age: Int)val client = KMongo.createClient()val database = client.getDatabase("test")val col = database.getCollection<Jedi>()runBlocking { col.insertOne(Jedi("Luke Skywalker", 19)) val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda")}
To learn more, refer to the Quick Start in the KMongo documentation.
Now that you have learned about the differences between KMongo and the MongoDB Kotlin driver, see the Quick Start to get started using the KMongo Kotlin driver.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4