From e9b5963c181662c7531cacfe8f75f2e067f10df9 Mon Sep 17 00:00:00 2001 From: cbullinger <115956901+cbullinger@users.noreply.github.com> Date: Mon, 12 Jun 2023 10:23:03 -0400 Subject: [PATCH 1/7] initial draft --- source/faq.txt | 10 +- source/includes/kmongo-description.rst | 5 + source/index.txt | 1 + source/legacy.draft.rst | 483 +++++++++++++++++++++++++ source/quick-start.txt | 2 +- 5 files changed, 494 insertions(+), 7 deletions(-) create mode 100644 source/includes/kmongo-description.rst create mode 100644 source/legacy.draft.rst diff --git a/source/faq.txt b/source/faq.txt index 8ff74535..2c0cd2b7 100644 --- a/source/faq.txt +++ b/source/faq.txt @@ -25,11 +25,7 @@ developed by the MongoDB team and provides a native API for Kotlin applications to connect to MongoDB and work with data. It is implemented by wrapping the :driver:`MongoDB Java driver `. -`KMongo `__ is a popular community-developed library -for working with MongoDB from Kotlin applications. -It is also a wrapper around the Java driver. -It was created prior to the creation of the official Kotlin driver to serve -the needs of the Kotlin community. +.. include:: /includes/kmongo-description.rst The Kotlin driver was developed in collaboration with the creator of KMongo, Julien Buret, to give users an officially-supported driver. @@ -48,11 +44,13 @@ key differences: - The official driver does *not* have built-in support for `reactor `__, `rxjava2 `__, `Jackson `__, or `GSON `__. -- The official driver does not support MongoDB shell commands. +- The official driver does *not* support MongoDB shell commands. - The official driver supports type-safe queries with the Builders API, whereas KMongo uses infix functions and property references for type-safe queries. +For more detailed information, see :ref:`Migrate from KMongo `. + .. _kotlin-faq-connection-pool: How Does Connection Pooling Work in the Kotlin Driver? diff --git a/source/includes/kmongo-description.rst b/source/includes/kmongo-description.rst new file mode 100644 index 00000000..1b8232a3 --- /dev/null +++ b/source/includes/kmongo-description.rst @@ -0,0 +1,5 @@ +`KMongo `__ is a popular community-developed library +for working with MongoDB from Kotlin applications. +It is also a wrapper around the Java driver. +It was created prior to the creation of the official Kotlin driver to serve +the needs of the Kotlin community. \ No newline at end of file diff --git a/source/index.txt b/source/index.txt index 9ff9d615..cbfd973c 100644 --- a/source/index.txt +++ b/source/index.txt @@ -16,6 +16,7 @@ MongoDB Kotlin Driver /connection-troubleshooting /issues-and-help /compatibility + /migrate-kmongo View the Source Introduction diff --git a/source/legacy.draft.rst b/source/legacy.draft.rst new file mode 100644 index 00000000..aee38a07 --- /dev/null +++ b/source/legacy.draft.rst @@ -0,0 +1,483 @@ +.. _kotlin-migrate-kmongo: + +=================== +Migrate from KMongo +=================== + +.. contents:: On this page + :local: + :backlinks: none + :depth: 1 + :class: singlecol + + +Overview +-------- + +In this section, you can identify the changes you need to make to migrate from +the KMongo coroutine driver to the MongoDB Kotlin driver. + +.. include:: /includes/kmongo-description.rst + +This page contains a high-level comparison of most of the ways the drivers differ. +Although both drivers :ref:`support synchronous and asynchronous operations `, +the examples on this page will use asynchronous coroutine-based operations. + +Connect to MongoDB Cluster +-------------------------- + +Both drivers let you connect to and communicate with MongoDB clusters from a +Kotlin application. + +KMongo +~~~~~~ + +To connect to a MongoDB cluster using KMongo with coroutines: + +.. code-block:: kotlin + + 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() + +Unlike the MongoDB Kotlin driver, KMongo allows the collection name to be +inferred from the data class name. + +MongoDB Kotlin Driver +~~~~~~~~~~~~~~~~~~~~~ + +To connect to a MongoDB cluster using the MongoDB Kotlin driver: + +.. code-block:: 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") + +See the :ref:`Connect to MongoDB ` documentation for more +information. + +CRUD and Aggregation +-------------------- + +Both drivers provide support for all MongoDB CRUD APIs and aggregation +operations. + +KMongo +~~~~~~ + +KMongo provides functions for all basic CRUD operations: + +.. code-block:: kotlin + + // 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") + +Aggregation pipelines can be built using the ``aggregate`` method and the +``pipeline`` function: + +.. code-block:: kotlin + + val avgAge = collection.aggregate( + 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. + +MongoDB Kotlin Driver +~~~~~~~~~~~~~~~~~~~~~ + +The MongoDB Kotlin driver also provides functions for all basic CRUD operations: + +.. code-block:: kotlin + + // 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) + +Aggregation pipelines can be built using the ``aggregate`` method and the +``pipeline`` function: + +.. code-block:: kotlin + + data class Results(val avgAge: Double) + + val resultsFlow = collection.aggregate( + 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 :ref:`CRUD Operations ` and +:ref:`Aggregation ` documentation for more information. + +Construct Queries +----------------- + +Both drivers provide support for type-safe queries using property references. + +KMongo +~~~~~~ + +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. + +.. code-block:: kotlin + + 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 also supports string queries that let you construct queries with +MongoDB Query Language: + +.. code-block:: kotlin + + 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("""[ {$match:{age:{$lt : ${yoda.age}}}}, + {$sample:{size:1}} + ]""").first() + +For more information, see the following KMongo documentation: + +- `Typed Queries `_ +- `Mongo Shell Queries `__ + +MongoDB Kotlin Driver +~~~~~~~~~~~~~~~~~~~~~ + +The MongoDB Kotlin driver uses the Builders API to construct queries. +Alternatively, you can use the ``Document`` class. + +.. code-block:: kotlin + + 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("people") + + // Using Builders + val filter = and(eq("gender", "female"), gt("age", 29)) + val projection = fields(excludeId(), include("email")) + val results = collection.find(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(filter).projection(projection) + +To map a KMongo string query to the Kotlin driver, you can use the ``JsonObject`` class. + +.. code-block:: kotlin + + val query = JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}") + val jsonResult = collection.find(query).firstOrNull() + +For more information, see the following Kotlin driver documentation: + +- :ref:`Builders ` +- :ref:`Documents ` guide +- `JsonObject <{+api+}/apidocs/bson/org/bson/json/JsonObject.html>`__ API Documentation + +Data Typing +----------- + +Both drivers support the use of Kotlin data classes as well as 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. + +KMongo +~~~~~~ + +You can use data classes and ``Document`` classes to model data in KMongo: + +.. code-block:: kotlin + + // With data class + data class Movie(val title: String, val year: Int, val rating: Float) + + val collection = database.getCollection("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") + + +MongoDB Kotlin Driver +~~~~~~~~~~~~~~~~~~~~~ + +You can use data classes and ``Document`` classes to model data with the +MongoDB Kotlin driver: + +.. code-block:: kotlin + + // With data class + data class Movie(val title: String, val year: Int, val rating: Float) + + val dataClassCollection = database.getCollection("movies") + val movieDataClass = dataClassCollection.findOneOrNull() + val movieNameDataClass = movieDataClass.title + + // With Document class + val documentCollection = database.getCollection("movies") + val movieDocument = documentCollection.findOneOrNull() + val movieTitleDocument = movieDocument.getString("title") + +Data Serialization +------------------ + +Both drivers provide support for serializing and deserializing data objects +in Kotlin to and from BSON. + +KMongo +~~~~~~ + +You can serialize data in KMongo using the following serialization libraries: + +* ``Jackson`` (default) +* ``POJO Codec engine`` +* ``kotlinx.serialization`` + +.. code-block:: kotlin + + // Using KotlinX Serialization + @Serializable + data class Data(@Contextual val _id: Id = 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. + +MongoDB Kotlin Driver +~~~~~~~~~~~~~~~~~~~~~ + +You can serialize data classes in the Kotlin driver using the ``kotlinx.serialization`` +library. + +The driver also provides an efficient ``Bson`` serializer that handles the +serialization of Kotlin objects to BSON data. + +.. code-block:: kotlin + + @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 + ) + +.. TODO DOCSP-29226 - add link to serialization docs +.. To learn more about serializing data classes with ``kotlinx.serialization``, +.. see the :ref:`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: + +.. code-block:: kotlin + + 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) + +To learn more about serializing data with the ``Document`` class, refer to + :ref:`Document Data Format: Extended JSON ` documentation. + +.. _kotlin-sync-async-support: + +Synchronous and Asynchronous Support +------------------------------------ + +Both drivers support synchronous and asynchronous operations. + +KMongo +~~~~~~ + +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 | KMongo Packages | +| --- | --- | +| Reactive Streams | ``org.litote.kmongo:kmongo-async`` | +| Coroutines | ``org.litote.kmongo.reactivestreams`` and ``org.litote.kmongo.coroutine`` | +| Reactor | ``org.litote.kmongo:kmongo-reactor`` | +| RxJava2 | ``org.litote.kmongo:kmongo-rxjava2`` | + +To write synchronous code with KMongo: + +.. code-block:: kotlin + + 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() + + // Synchronous operations + col.insertOne(Jedi("Luke Skywalker", 19)) + val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda") + +To write async coroutine code with KMongo: + +.. code-block:: kotlin + + 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() + + runBlocking { + + // Async operations + 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. + +MongoDB Kotlin Driver +~~~~~~~~~~~~~~~~~~~~~ + +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: + +.. code-block:: kotlin + + import com.mongodb.kotlin.client.MongoClient + + // Instantiate your collection + data class Jedi(val name: String, val age: Int) + val uri = " + val mongoClient = MongoClient.create(uri) + val database = mongoClient.getDatabase("test") + val collection = database.getCollection("jedi") + + // Synchronous operations + val jedi =a Jedi("Luke Skywalker", 19) + collection.insertOne(jedi) + +To write asynchronous coroutine code: + +.. code-block:: kotlin + + import com.mongodb.kotlin.client.coroutine.MongoClient + + // Instantiate your collection + data class Jedi(val name: String, val age: Int) + val uri = " + val mongoClient = MongoClient.create(uri) + val database = mongoClient.getDatabase("test") + val collection = database.getCollection("jedi") + + runBlocking { + + // Async operations + val jedi =a Jedi("Luke Skywalker", 19) + collection.insertOne(jedi) + } + +What Next? +---------- + +Now that you have learned about the differences between KMongo and the MongoDB +Kotlin driver, see the :ref:`Quick Start ` to get +started using the KMongo Kotlin driver. diff --git a/source/quick-start.txt b/source/quick-start.txt index d7a86939..cb0b143c 100644 --- a/source/quick-start.txt +++ b/source/quick-start.txt @@ -1,4 +1,4 @@ -.. _kotlin-sync-quickstart: +.. _kotlin-quickstart: =========== Quick Start From 3d88e2809814d23b7427bf86d7304e35ff124469 Mon Sep 17 00:00:00 2001 From: cbullinger <115956901+cbullinger@users.noreply.github.com> Date: Fri, 16 Jun 2023 10:38:35 -0400 Subject: [PATCH 2/7] Rename file --- source/{legacy.draft.rst => migrate-kmongo.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename source/{legacy.draft.rst => migrate-kmongo.txt} (100%) diff --git a/source/legacy.draft.rst b/source/migrate-kmongo.txt similarity index 100% rename from source/legacy.draft.rst rename to source/migrate-kmongo.txt From 3eb1a5cf7811aa8e42ca740ee3e635dfc5d84e22 Mon Sep 17 00:00:00 2001 From: cbullinger <115956901+cbullinger@users.noreply.github.com> Date: Fri, 16 Jun 2023 10:51:13 -0400 Subject: [PATCH 3/7] fix tables --- source/migrate-kmongo.txt | 44 +++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/source/migrate-kmongo.txt b/source/migrate-kmongo.txt index aee38a07..a55062ec 100644 --- a/source/migrate-kmongo.txt +++ b/source/migrate-kmongo.txt @@ -14,7 +14,7 @@ Migrate from KMongo Overview -------- -In this section, you can identify the changes you need to make to migrate from +In this page, you can identify the changes you need to make to migrate from the KMongo coroutine driver to the MongoDB Kotlin driver. .. include:: /includes/kmongo-description.rst @@ -373,12 +373,25 @@ separate companion libraries that provide asynchronous support to the core libra KMongo supports the following asynchronous paradigms: -| Async Style | KMongo Packages | -| --- | --- | -| Reactive Streams | ``org.litote.kmongo:kmongo-async`` | -| Coroutines | ``org.litote.kmongo.reactivestreams`` and ``org.litote.kmongo.coroutine`` | -| Reactor | ``org.litote.kmongo:kmongo-reactor`` | -| RxJava2 | ``org.litote.kmongo:kmongo-rxjava2`` | +.. list-table:: + :header-rows: 1 + :stub-columns: 1 + :widths: 10 40 + + * - 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: @@ -430,10 +443,19 @@ 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`` | +.. list-table:: + :header-rows: 1 + :stub-columns: 1 + :widths: 10 40 + + * - 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. From 9958503af501597f86c79b1df8d69654f2f43cf5 Mon Sep 17 00:00:00 2001 From: cbullinger <115956901+cbullinger@users.noreply.github.com> Date: Fri, 16 Jun 2023 11:37:47 -0400 Subject: [PATCH 4/7] Reformat as tabs --- source/migrate-kmongo.txt | 621 +++++++++++++++++++------------------- 1 file changed, 315 insertions(+), 306 deletions(-) diff --git a/source/migrate-kmongo.txt b/source/migrate-kmongo.txt index a55062ec..5454da81 100644 --- a/source/migrate-kmongo.txt +++ b/source/migrate-kmongo.txt @@ -15,7 +15,7 @@ Overview -------- In this page, you can identify the changes you need to make to migrate from -the KMongo coroutine driver to the MongoDB Kotlin driver. +the KMongo driver to the official MongoDB Kotlin driver. .. include:: /includes/kmongo-description.rst @@ -29,50 +29,52 @@ Connect to MongoDB Cluster Both drivers let you connect to and communicate with MongoDB clusters from a Kotlin application. -KMongo -~~~~~~ +.. tabs:: -To connect to a MongoDB cluster using KMongo with coroutines: + .. tab:: + :tabid: {+driver-long+} -.. code-block:: kotlin + To connect to a MongoDB cluster using the MongoDB Kotlin driver: - import org.litote.kmongo.reactivestreams.* - import org.litote.kmongo.coroutine.* + .. code-block:: kotlin - data class Jedi(val name: String, val age: Int) + import com.mongodb.kotlin.client.coroutine.MongoClient - // 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() + data class Jedi(val name: String, val age: Int) -Unlike the MongoDB Kotlin driver, KMongo allows the collection name to be -inferred from the data class name. + // Replace the placeholder with your MongoDB deployment's connection string + val uri = CONNECTION_STRING_URI_PLACEHOLDER -MongoDB Kotlin Driver -~~~~~~~~~~~~~~~~~~~~~ + val mongoClient = MongoClient.create(uri) + + val database = mongoClient.getDatabase("test") + // Get a collection of documents of type Jedi + val collection = database.getCollection("jedi") -To connect to a MongoDB cluster using the MongoDB Kotlin driver: + See the :ref:`Connect to MongoDB ` documentation for more + information. + + .. tab:: + :tabid: KMongo -.. code-block:: kotlin + To connect to a MongoDB cluster using KMongo with coroutines: - import com.mongodb.kotlin.client.coroutine.MongoClient + .. code-block:: kotlin - data class Jedi(val name: String, val age: Int) + import org.litote.kmongo.reactivestreams.* + import org.litote.kmongo.coroutine.* - // Replace the placeholder with your MongoDB deployment's connection string - val uri = CONNECTION_STRING_URI_PLACEHOLDER + data class Jedi(val name: String, val age: Int) - val mongoClient = MongoClient.create(uri) - - val database = mongoClient.getDatabase("test") - // Get a collection of documents of type Jedi - val collection = database.getCollection("jedi") + // 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() -See the :ref:`Connect to MongoDB ` documentation for more -information. + Unlike the MongoDB Kotlin driver, KMongo allows the collection name to be + inferred from the data class name. CRUD and Aggregation -------------------- @@ -80,165 +82,169 @@ CRUD and Aggregation Both drivers provide support for all MongoDB CRUD APIs and aggregation operations. -KMongo -~~~~~~ +.. tabs:: -KMongo provides functions for all basic CRUD operations: + .. tab:: + :tabid: {+driver-long+} -.. code-block:: kotlin + The MongoDB Kotlin driver also provides functions for all basic CRUD operations: - // Insert a document - val jedi = Jedi("Luke Skywalker", 19) - col.insertOne(jedi) + .. code-block:: kotlin - // Find a document - val luke = col.findOne(Jedi::name eq "Luke Skywalker") - val jedis = col.find(Jedi::age lt 30).toList() + // Insert a document + val jedi =a Jedi("Luke Skywalker", 19) + collection.insertOne(jedi) - // Update a document - col.updateOne(Jedi::name eq "Luke Skywalker", setValue(Jedi::age, 20)) + // Find a document + val luke = collection.find(Jedi::name.name, "Luke Skywalker") + val jedis = collection.find(lt(Jedi::age.name, 30)).toList() - // Delete a document - col.deleteOne(Jedi::name eq "Luke Skywalker") + // Update a document + val filter = Filters.eq(Jedi::name.name, "Luke Skywalker") + val update = Updates.set(Jedi::age.name, 20) + collection.updateOne(filter, update) -Aggregation pipelines can be built using the ``aggregate`` method and the -``pipeline`` function: + // Delete a document + val filter = Filters.eq(Jedi::name.name, "Luke Skywalker") + collection.deleteOne(filter) -.. code-block:: kotlin + Aggregation pipelines can be built using the ``aggregate`` method and the + ``pipeline`` function: - val avgAge = collection.aggregate( - pipeline( - match(Jedi::name ne "Luke Skywalker"), - group(Jedi::name, avg(Jedi::age)) - ) - ).toList() + .. code-block:: kotlin -For more information on available methods, see the -`Extensions Overview `__ KMongo -documentation. + data class Results(val avgAge: Double) -MongoDB Kotlin Driver -~~~~~~~~~~~~~~~~~~~~~ + val resultsFlow = collection.aggregate( + 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) } -The MongoDB Kotlin driver also provides functions for all basic CRUD operations: + See the :ref:`CRUD Operations ` and + :ref:`Aggregation ` documentation for more information. + + .. tab:: + :tabid: KMongo -.. code-block:: kotlin + KMongo provides functions for all basic CRUD operations: - // Insert a document - val jedi =a Jedi("Luke Skywalker", 19) - collection.insertOne(jedi) + .. code-block:: kotlin - // Find a document - val luke = collection.find(Jedi::name.name, "Luke Skywalker") - val jedis = collection.find(lt(Jedi::age.name, 30)).toList() + // Insert a document + val jedi = Jedi("Luke Skywalker", 19) + col.insertOne(jedi) - // Update a document - val filter = Filters.eq(Jedi::name.name, "Luke Skywalker") - val update = Updates.set(Jedi::age.name, 20) - collection.updateOne(filter, update) + // Find a document + val luke = col.findOne(Jedi::name eq "Luke Skywalker") + val jedis = col.find(Jedi::age lt 30).toList() - // Delete a document - val filter = Filters.eq(Jedi::name.name, "Luke Skywalker") - collection.deleteOne(filter) + // Update a document + col.updateOne(Jedi::name eq "Luke Skywalker", setValue(Jedi::age, 20)) -Aggregation pipelines can be built using the ``aggregate`` method and the -``pipeline`` function: + // Delete a document + col.deleteOne(Jedi::name eq "Luke Skywalker") -.. code-block:: kotlin + Aggregation pipelines can be built using the ``aggregate`` method and the + ``pipeline`` function: - data class Results(val avgAge: Double) + .. code-block:: kotlin - val resultsFlow = collection.aggregate( - 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) } + val avgAge = collection.aggregate( + pipeline( + match(Jedi::name ne "Luke Skywalker"), + group(Jedi::name, avg(Jedi::age)) + ) + ).toList() -See the :ref:`CRUD Operations ` and -:ref:`Aggregation ` documentation for more information. + For more information on available methods, see the + `Extensions Overview `__ KMongo + documentation. Construct Queries ----------------- Both drivers provide support for type-safe queries using property references. -KMongo -~~~~~~ +.. tabs:: -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. + .. tab:: + :tabid: {+driver-long+} -.. code-block:: kotlin + The MongoDB Kotlin driver uses the Builders API to construct queries. + Alternatively, you can use the ``Document`` class. - data class Jedi(val name: String) + .. code-block:: kotlin - val yoda = col.findOne(Jedi::name eq "Yoda") + data class Person(val name: String, val email: String, val gender: String, val age: Int) + data class Results(val email: String) - // Compile error (2 is not a String) - val error = col.findOne(Jedi::name eq 2) + val collection = database.getCollection("people") - // Use property reference with instances - val yoda2 = col.findOne(yoda::name regex "Yo.*") + // Using Builders + val filter = and(eq("gender", "female"), gt("age", 29)) + val projection = fields(excludeId(), include("email")) + val results = collection.find(filter).projection(projection) -KMongo also supports string queries that let you construct queries with -MongoDB Query Language: + // 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(filter).projection(projection) -.. code-block:: kotlin + To map a KMongo string query to the Kotlin driver, you can use the ``JsonObject`` class. - import org.litote.kmongo.MongoOperator.lt - import org.litote.kmongo.MongoOperator.match - import org.litote.kmongo.MongoOperator.regex - import org.litote.kmongo.MongoOperator.sample + .. code-block:: kotlin - val yoda = col.findOne("{name: {$regex: 'Yo.*'}}")!! - val luke = col.aggregate("""[ {$match:{age:{$lt : ${yoda.age}}}}, - {$sample:{size:1}} - ]""").first() + val query = JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}") + val jsonResult = collection.find(query).firstOrNull() -For more information, see the following KMongo documentation: + For more information, see the following Kotlin driver documentation: -- `Typed Queries `_ -- `Mongo Shell Queries `__ + - :ref:`Builders ` + - :ref:`Documents ` guide + - `JsonObject <{+api+}/apidocs/bson/org/bson/json/JsonObject.html>`__ API Documentation + + .. tab:: + :tabid: KMongo -MongoDB Kotlin Driver -~~~~~~~~~~~~~~~~~~~~~ + 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. -The MongoDB Kotlin driver uses the Builders API to construct queries. -Alternatively, you can use the ``Document`` class. + .. code-block:: kotlin -.. code-block:: kotlin + data class Jedi(val name: String) - data class Person(val name: String, val email: String, val gender: String, val age: Int) - data class Results(val email: String) + val yoda = col.findOne(Jedi::name eq "Yoda") - val collection = database.getCollection("people") + // Compile error (2 is not a String) + val error = col.findOne(Jedi::name eq 2) - // Using Builders - val filter = and(eq("gender", "female"), gt("age", 29)) - val projection = fields(excludeId(), include("email")) - val results = collection.find(filter).projection(projection) + // Use property reference with instances + val yoda2 = col.findOne(yoda::name regex "Yo.*") - // 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(filter).projection(projection) + KMongo also supports string queries that let you construct queries with + MongoDB Query Language: -To map a KMongo string query to the Kotlin driver, you can use the ``JsonObject`` class. + .. code-block:: kotlin -.. code-block:: kotlin + 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 query = JsonObject("{\"name\": \"Gabriel Garc\\u00eda M\\u00e1rquez\"}") - val jsonResult = collection.find(query).firstOrNull() + val yoda = col.findOne("{name: {$regex: 'Yo.*'}}")!! + val luke = col.aggregate("""[ {$match:{age:{$lt : ${yoda.age}}}}, + {$sample:{size:1}} + ]""").first() -For more information, see the following Kotlin driver documentation: + For more information, see the following KMongo documentation: -- :ref:`Builders ` -- :ref:`Documents ` guide -- `JsonObject <{+api+}/apidocs/bson/org/bson/json/JsonObject.html>`__ API Documentation + - `Typed Queries `_ + - `Mongo Shell Queries `__ Data Typing ----------- @@ -247,45 +253,46 @@ Both drivers support the use of Kotlin data classes as well as the ``Document`` model the data stored in a MongoDB collection. The ``Document`` class lets you model data represented in a MongoDB collection in a flexible format. -KMongo -~~~~~~ +.. tabs:: -You can use data classes and ``Document`` classes to model data in KMongo: + .. tab:: + :tabid: {+driver-long+} -.. code-block:: kotlin + You can use data classes and ``Document`` classes to model data with the + MongoDB Kotlin driver: - // With data class - data class Movie(val title: String, val year: Int, val rating: Float) + .. code-block:: kotlin - val collection = database.getCollection("movies") - val movieDataClass = dataClassCollection.findOne() - val movieNameDataClass = movieDataClass.title + // With data class + data class Movie(val title: String, val year: Int, val rating: Float) - // With Document class - val documentCollection = database.getCollection("movies") - val movieDocument = documentCollection.findOne() - val movieTitleDocument = movieDocument.getString("title") + val dataClassCollection = database.getCollection("movies") + val movieDataClass = dataClassCollection.findOneOrNull() + val movieNameDataClass = movieDataClass.title + // With Document class + val documentCollection = database.getCollection("movies") + val movieDocument = documentCollection.findOneOrNull() + val movieTitleDocument = movieDocument.getString("title") -MongoDB Kotlin Driver -~~~~~~~~~~~~~~~~~~~~~ + .. tab:: + :tabid: KMongo -You can use data classes and ``Document`` classes to model data with the -MongoDB Kotlin driver: + You can use data classes and ``Document`` classes to model data in KMongo: -.. code-block:: kotlin + .. code-block:: kotlin - // With data class - data class Movie(val title: String, val year: Int, val rating: Float) + // With data class + data class Movie(val title: String, val year: Int, val rating: Float) - val dataClassCollection = database.getCollection("movies") - val movieDataClass = dataClassCollection.findOneOrNull() - val movieNameDataClass = movieDataClass.title + val collection = database.getCollection("movies") + val movieDataClass = dataClassCollection.findOne() + val movieNameDataClass = movieDataClass.title - // With Document class - val documentCollection = database.getCollection("movies") - val movieDocument = documentCollection.findOneOrNull() - val movieTitleDocument = movieDocument.getString("title") + // With Document class + val documentCollection = database.getCollection("movies") + val movieDocument = documentCollection.findOne() + val movieTitleDocument = movieDocument.getString("title") Data Serialization ------------------ @@ -293,70 +300,70 @@ Data Serialization Both drivers provide support for serializing and deserializing data objects in Kotlin to and from BSON. -KMongo -~~~~~~ +.. tabs:: -You can serialize data in KMongo using the following serialization libraries: + .. tab:: + :tabid: {+driver-long+} -* ``Jackson`` (default) -* ``POJO Codec engine`` -* ``kotlinx.serialization`` + You can serialize data classes in the Kotlin driver using the ``kotlinx.serialization`` + library. The driver provides an efficient ``Bson`` serializer that handles the + serialization of Kotlin objects to BSON data. -.. code-block:: kotlin - - // Using KotlinX Serialization - @Serializable - data class Data(@Contextual val _id: Id = newId()) + .. code-block:: kotlin - val json = Json { serializersModule = IdKotlinXSerializationModule } - val data = Data() - val json = json.encodeToString(data) + @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 + ) -To learn more about the KMongo serialization methods, refer to the -`Object Mapping `__ -KMongo documentation. + .. TODO DOCSP-29226 - add link to serialization docs + .. To learn more about serializing data classes with ``kotlinx.serialization``, + .. see the :ref:`Kotlin Serialization ` documentation. -MongoDB Kotlin Driver -~~~~~~~~~~~~~~~~~~~~~ + If you use the ``Document`` class to represent your collection, you can + serialize it to JSON and EJSON using the ``.toJson()`` method: -You can serialize data classes in the Kotlin driver using the ``kotlinx.serialization`` -library. + .. code-block:: kotlin -The driver also provides an efficient ``Bson`` serializer that handles the -serialization of Kotlin objects to BSON data. + val document = Document("_id", 1).append("color", "blue") -.. code-block:: kotlin + // Serialize to JSON + document.toJson() - @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 - ) + // Serialize to EJSON + val settings = JsonWriterSettings.builder().outputMode(JsonMode.STRICT).build() + val json = doc.toJson(settings) -.. TODO DOCSP-29226 - add link to serialization docs -.. To learn more about serializing data classes with ``kotlinx.serialization``, -.. see the :ref:`Kotlin Serialization ` documentation. + To learn more about serializing data with the ``Document`` class, refer to + :ref:`Document Data Format: Extended JSON ` documentation. -If you use the ``Document`` class to represent your collection, you can -serialize it to JSON and EJSON using the ``.toJson()`` method: + .. tab:: + :tabid: KMongo -.. code-block:: kotlin + You can serialize data in KMongo using the following serialization libraries: - val document = Document("_id", 1).append("color", "blue") + * ``Jackson`` (default) + * ``POJO Codec engine`` + * ``kotlinx.serialization`` - // Serialize to JSON - document.toJson() + .. code-block:: kotlin + + // Using KotlinX Serialization + @Serializable + data class Data(@Contextual val _id: Id = newId()) - // Serialize to EJSON - val settings = JsonWriterSettings.builder().outputMode(JsonMode.STRICT).build() - val json = doc.toJson(settings) + val json = Json { serializersModule = IdKotlinXSerializationModule } + val data = Data() + val json = json.encodeToString(data) -To learn more about serializing data with the ``Document`` class, refer to - :ref:`Document Data Format: Extended JSON ` documentation. + To learn more about the KMongo serialization methods, refer to the + `Object Mapping `__ + KMongo documentation. .. _kotlin-sync-async-support: @@ -365,137 +372,139 @@ Synchronous and Asynchronous Support Both drivers support synchronous and asynchronous operations. -KMongo -~~~~~~ +.. tabs:: -KMongo has a core library ``org.litote.kmongo:kmongo`` with main functionality and -separate companion libraries that provide asynchronous support to the core library. + .. tab:: + :tabid: {+driver-long+} -KMongo supports the following asynchronous paradigms: + 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. -.. list-table:: - :header-rows: 1 - :stub-columns: 1 - :widths: 10 40 + .. list-table:: + :header-rows: 1 + :stub-columns: 1 + :widths: 10 40 - * - Async Style - - Package + * - Driver + - Package - * - Reactive Streams - - | ``org.litote.kmongo:kmongo-async`` + * - Sync + - | ``com.mongodb.kotlin.client`` - * - Coroutines - - | ``com.mongodb.kotlin.client.coroutine`` and ``org.litote.kmongo.coroutine`` + * - Coroutines + - | ``com.mongodb.kotlin.client.coroutine`` - * - Reactor - - | ``org.litote.kmongo:kmongo-reactor`` + Unlike KMongo, if you want to write asynchronous code, you only need to import + the relevant package. - * - RxJava2 - - | ``org.litote.kmongo:kmongo-rxjava2`` + To write synchronous code: -To write synchronous code with KMongo: + .. code-block:: kotlin -.. code-block:: kotlin + import com.mongodb.kotlin.client.MongoClient - import org.litote.kmongo.* - - // Instantiate your collection - data class Jedi(val name: String, val age: Int) + // Instantiate your collection + data class Jedi(val name: String, val age: Int) + val uri = " + val mongoClient = MongoClient.create(uri) + val database = mongoClient.getDatabase("test") + val collection = database.getCollection("jedi") - val client = KMongo.createClient() - val database = client.getDatabase("test") - val col = database.getCollection() - - // Synchronous operations - col.insertOne(Jedi("Luke Skywalker", 19)) - val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda") + // Synchronous operations + val jedi =a Jedi("Luke Skywalker", 19) + collection.insertOne(jedi) -To write async coroutine code with KMongo: + To write asynchronous coroutine code: -.. code-block:: kotlin + .. code-block:: kotlin - import org.litote.kmongo.reactivestreams.* - import org.litote.kmongo.coroutine.* + import com.mongodb.kotlin.client.coroutine.MongoClient - // Instantiate your collection - data class Jedi(val name: String, val age: Int) + // Instantiate your collection + data class Jedi(val name: String, val age: Int) + val uri = " + val mongoClient = MongoClient.create(uri) + val database = mongoClient.getDatabase("test") + val collection = database.getCollection("jedi") - val client = KMongo.createClient() - val database = client.getDatabase("test") - val col = database.getCollection() + runBlocking { - runBlocking { - - // Async operations - col.insertOne(Jedi("Luke Skywalker", 19)) - val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda") - } + // Async operations + val jedi =a Jedi("Luke Skywalker", 19) + collection.insertOne(jedi) + } + + .. tab:: + :tabid: KMongo -To learn more, refer to the `Quick Start `__ -in the KMongo documentation. + KMongo has a core library ``org.litote.kmongo:kmongo`` with main functionality and + separate companion libraries that provide asynchronous support to the core library. -MongoDB Kotlin Driver -~~~~~~~~~~~~~~~~~~~~~ + KMongo supports the following asynchronous paradigms: -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. + .. list-table:: + :header-rows: 1 + :stub-columns: 1 + :widths: 10 40 -.. list-table:: - :header-rows: 1 - :stub-columns: 1 - :widths: 10 40 + * - Async Style + - Package - * - Driver - - Package + * - Reactive Streams + - | ``org.litote.kmongo:kmongo-async`` - * - Sync - - | ``com.mongodb.kotlin.client`` + * - Coroutines + - | ``com.mongodb.kotlin.client.coroutine`` and ``org.litote.kmongo.coroutine`` - * - Coroutines - - | ``com.mongodb.kotlin.client.coroutine`` + * - Reactor + - | ``org.litote.kmongo:kmongo-reactor`` -Unlike KMongo, if you want to write asynchronous code, you only need to import -the relevant package. + * - RxJava2 + - | ``org.litote.kmongo:kmongo-rxjava2`` -To write synchronous code: + To write synchronous code with KMongo: -.. code-block:: kotlin + .. code-block:: kotlin - import com.mongodb.kotlin.client.MongoClient + import org.litote.kmongo.* + + // Instantiate your collection + data class Jedi(val name: String, val age: Int) - // Instantiate your collection - data class Jedi(val name: String, val age: Int) - val uri = " - val mongoClient = MongoClient.create(uri) - val database = mongoClient.getDatabase("test") - val collection = database.getCollection("jedi") + val client = KMongo.createClient() + val database = client.getDatabase("test") + val col = database.getCollection() + + // Synchronous operations + col.insertOne(Jedi("Luke Skywalker", 19)) + val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda") - // Synchronous operations - val jedi =a Jedi("Luke Skywalker", 19) - collection.insertOne(jedi) + To write async coroutine code with KMongo: -To write asynchronous coroutine code: + .. code-block:: kotlin -.. code-block:: kotlin + import org.litote.kmongo.reactivestreams.* + import org.litote.kmongo.coroutine.* - import com.mongodb.kotlin.client.coroutine.MongoClient + // Instantiate your collection + data class Jedi(val name: String, val age: Int) - // Instantiate your collection - data class Jedi(val name: String, val age: Int) - val uri = " - val mongoClient = MongoClient.create(uri) - val database = mongoClient.getDatabase("test") - val collection = database.getCollection("jedi") + val client = KMongo.createClient() + val database = client.getDatabase("test") + val col = database.getCollection() - runBlocking { + runBlocking { + + // Async operations + col.insertOne(Jedi("Luke Skywalker", 19)) + val yoda : Jedi? = col.findOne(Jedi::name eq "Yoda") + } - // Async operations - val jedi =a Jedi("Luke Skywalker", 19) - collection.insertOne(jedi) - } + To learn more, refer to the `Quick Start `__ + in the KMongo documentation. What Next? ---------- From 746de4ad8eb0d2500880431787719ea8a87c93f1 Mon Sep 17 00:00:00 2001 From: cbullinger <115956901+cbullinger@users.noreply.github.com> Date: Tue, 20 Jun 2023 08:03:39 -0400 Subject: [PATCH 5/7] tweak intro wording --- source/migrate-kmongo.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/migrate-kmongo.txt b/source/migrate-kmongo.txt index 5454da81..7a0ee94a 100644 --- a/source/migrate-kmongo.txt +++ b/source/migrate-kmongo.txt @@ -14,11 +14,13 @@ Migrate from KMongo Overview -------- -In this page, you can identify the changes you need to make to migrate from -the KMongo driver to the official MongoDB Kotlin driver. +In this page, you can identify the changes you need to make to migrate from the KMongo driver to the official MongoDB Kotlin driver. .. include:: /includes/kmongo-description.rst +The MongoDB Kotlin driver is the officially supported and maintained MongoDB driver for +Kotlin. It is developed by the MongoDB team. + This page contains a high-level comparison of most of the ways the drivers differ. Although both drivers :ref:`support synchronous and asynchronous operations `, the examples on this page will use asynchronous coroutine-based operations. From 42d4329abe44d80d834b90045b05c8847cf12d2e Mon Sep 17 00:00:00 2001 From: cbullinger Date: Fri, 28 Jul 2023 07:38:27 -0400 Subject: [PATCH 6/7] Address feedback and note KMongo as deprecated --- source/includes/kmongo-description.rst | 2 +- source/migrate-kmongo.txt | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/source/includes/kmongo-description.rst b/source/includes/kmongo-description.rst index 1b8232a3..cc3ecbda 100644 --- a/source/includes/kmongo-description.rst +++ b/source/includes/kmongo-description.rst @@ -2,4 +2,4 @@ for working with MongoDB from Kotlin applications. It is also a wrapper around the Java driver. It was created prior to the creation of the official Kotlin driver to serve -the needs of the Kotlin community. \ No newline at end of file +the needs of the Kotlin community. As of July 2023, it has been marked as deprecated. \ No newline at end of file diff --git a/source/migrate-kmongo.txt b/source/migrate-kmongo.txt index 7a0ee94a..b27a7199 100644 --- a/source/migrate-kmongo.txt +++ b/source/migrate-kmongo.txt @@ -14,14 +14,16 @@ Migrate from KMongo Overview -------- -In this page, you can identify the changes you need to make to migrate from the KMongo driver to the official MongoDB Kotlin driver. +This page contains a high-level comparison of most of the ways the official +MongoDB Kotlin 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. .. include:: /includes/kmongo-description.rst The MongoDB Kotlin driver is the officially supported and maintained MongoDB driver for Kotlin. It is developed by the MongoDB team. -This page contains a high-level comparison of most of the ways the drivers differ. Although both drivers :ref:`support synchronous and asynchronous operations `, the examples on this page will use asynchronous coroutine-based operations. @@ -307,8 +309,9 @@ in Kotlin to and from BSON. .. tab:: :tabid: {+driver-long+} - You can serialize data classes in the Kotlin driver using the ``kotlinx.serialization`` - library. The driver provides an efficient ``Bson`` serializer that handles the + You can serialize data classes in the Kotlin driver using both automatic + data class codecs as well as the ``kotlinx.serialization`` library. The + driver provides an efficient ``Bson`` serializer that handles the serialization of Kotlin objects to BSON data. .. code-block:: kotlin @@ -323,9 +326,8 @@ in Kotlin to and from BSON. val manufacturer: String = "Acme" // Use instead of @BsonProperty ) - .. TODO DOCSP-29226 - add link to serialization docs - .. To learn more about serializing data classes with ``kotlinx.serialization``, - .. see the :ref:`Kotlin Serialization ` documentation. + To learn more, see the :ref:`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: @@ -342,7 +344,7 @@ in Kotlin to and from BSON. val json = doc.toJson(settings) To learn more about serializing data with the ``Document`` class, refer to - :ref:`Document Data Format: Extended JSON ` documentation. + :ref:`Document Data Format - Extended JSON ` documentation. .. tab:: :tabid: KMongo From 5790232c06d6a18a8f9b9e9a42f11a7223f8e7bb Mon Sep 17 00:00:00 2001 From: cbullinger Date: Fri, 28 Jul 2023 08:17:02 -0400 Subject: [PATCH 7/7] Fix autobuilder error --- source/migrate-kmongo.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/migrate-kmongo.txt b/source/migrate-kmongo.txt index b27a7199..8b8938be 100644 --- a/source/migrate-kmongo.txt +++ b/source/migrate-kmongo.txt @@ -207,7 +207,7 @@ Both drivers provide support for type-safe queries using property references. For more information, see the following Kotlin driver documentation: - - :ref:`Builders ` + - :ref:`Builders ` - :ref:`Documents ` guide - `JsonObject <{+api+}/apidocs/bson/org/bson/json/JsonObject.html>`__ API Documentation