diff --git a/examples/src/test/kotlin/ClientBulkTest.kt b/examples/src/test/kotlin/ClientBulkTest.kt index ce495bb9..f5de66ee 100644 --- a/examples/src/test/kotlin/ClientBulkTest.kt +++ b/examples/src/test/kotlin/ClientBulkTest.kt @@ -1,7 +1,11 @@ import com.mongodb.MongoNamespace import com.mongodb.client.model.Filters +import com.mongodb.client.model.Sorts +import com.mongodb.client.model.Updates import com.mongodb.client.model.bulk.ClientBulkWriteOptions import com.mongodb.client.model.bulk.ClientNamespacedWriteModel +import com.mongodb.client.model.bulk.ClientReplaceOneOptions +import com.mongodb.client.model.bulk.ClientUpdateOneOptions import com.mongodb.kotlin.client.coroutine.MongoClient import config.getConfig import kotlinx.coroutines.runBlocking @@ -19,11 +23,14 @@ internal class ClientBulkTest { data class Person( @BsonId val id: Int, val name: String, + val age: Int? = null, ) data class Object( @BsonId val id: Int, val type: String, + val category: String? = null, + val manufacturer: String? = null, ) // :snippet-end: @@ -40,7 +47,14 @@ internal class ClientBulkTest { fun beforeAll() { runBlocking { personCollection.insertOne(Person(1, "Sandy King")) - objectCollection.insertOne(Object(1, "artist easel")) + personCollection.insertOne(Person(1, "Freya Polk", 34)) + objectCollection.insertMany( + listOf( + Object(1, "artist easel"), + Object(2, "keyboard", "electronic"), + Object(3, "blender", "electronic"), + ) + ) } } @@ -62,18 +76,20 @@ internal class ClientBulkTest { // :snippet-start: insert-models val docsToInsert = mutableListOf() - docsToInsert.add(ClientNamespacedWriteModel - .insertOne( - MongoNamespace("sample_db", "people"), - Person(2, "Julia Smith") - ) + docsToInsert.add( + ClientNamespacedWriteModel + .insertOne( + MongoNamespace("sample_db", "people"), + Person(2, "Julia Smith") + ) ) - docsToInsert.add(ClientNamespacedWriteModel - .insertOne( - MongoNamespace("sample_db", "objects"), - Object(2, "washing machine") - ) + docsToInsert.add( + ClientNamespacedWriteModel + .insertOne( + MongoNamespace("sample_db", "objects"), + Object(2, "washing machine") + ) ) val clientBulkResult = client.bulkWrite(docsToInsert) @@ -84,25 +100,60 @@ internal class ClientBulkTest { assertEquals(2, personCollection.countDocuments()) } + + // Ignoring tests because successful completion of + // writes is blocked on https://jira.mongodb.org/browse/CLOUDP-288992 + @Ignore + fun updateOperationTest() = runBlocking { + // :snippet-start: update-models + val docsToInsert = mutableListOf() + + docsToInsert.add( + ClientNamespacedWriteModel + .updateOne( + MongoNamespace("sample_db", "people"), + Filters.eq(Person::name.name, "Freya Polk"), + Updates.inc(Person::age.name, 1) + ) + ) + + docsToInsert.add( + ClientNamespacedWriteModel + .updateMany( + MongoNamespace("sample_db", "objects"), + Filters.eq(Object::category.name, "electronic"), + Updates.set(Object::manufacturer.name, "Premium Technologies") + ) + ) + + val clientBulkResult = client.bulkWrite(docsToInsert) + // :snippet-end: + + // Junit test for the above code + assertEquals(3, clientBulkResult.modifiedCount) + } + @Ignore fun replaceOperationTest() = runBlocking { // :snippet-start: replace-models val docsReplacements = mutableListOf() - docsReplacements.add(ClientNamespacedWriteModel - .replaceOne( - MongoNamespace("sample_db", "people"), - Filters.eq(Person::id.name, 1), - Person(1, "Frederic Hilbert") - ) + docsReplacements.add( + ClientNamespacedWriteModel + .replaceOne( + MongoNamespace("sample_db", "people"), + Filters.eq(Person::id.name, 1), + Person(1, "Frederic Hilbert") + ) ) - docsReplacements.add(ClientNamespacedWriteModel - .replaceOne( - MongoNamespace("sample_db", "objects"), - Filters.eq(Object::id.name, 1), - Object(1, "ironing board") - ) + docsReplacements.add( + ClientNamespacedWriteModel + .replaceOne( + MongoNamespace("sample_db", "objects"), + Filters.eq(Object::id.name, 1), + Object(1, "ironing board") + ) ) val clientBulkResult = client.bulkWrite(docsReplacements) diff --git a/source/examples/generated/ClientBulkTest.snippet.data-classes.kt b/source/examples/generated/ClientBulkTest.snippet.data-classes.kt index 0fd79714..368dcfd2 100644 --- a/source/examples/generated/ClientBulkTest.snippet.data-classes.kt +++ b/source/examples/generated/ClientBulkTest.snippet.data-classes.kt @@ -1,9 +1,12 @@ data class Person( @BsonId val id: Int, val name: String, + val age: Int? = null, ) data class Object( @BsonId val id: Int, val type: String, + val category: String? = null, + val manufacturer: String? = null, ) diff --git a/source/examples/generated/ClientBulkTest.snippet.insert-models.kt b/source/examples/generated/ClientBulkTest.snippet.insert-models.kt index 4473334e..d82201a8 100644 --- a/source/examples/generated/ClientBulkTest.snippet.insert-models.kt +++ b/source/examples/generated/ClientBulkTest.snippet.insert-models.kt @@ -1,17 +1,19 @@ val docsToInsert = mutableListOf() -docsToInsert.add(ClientNamespacedWriteModel - .insertOne( - MongoNamespace("sample_db", "people"), - Person(2, "Julia Smith") - ) +docsToInsert.add( + ClientNamespacedWriteModel + .insertOne( + MongoNamespace("sample_db", "people"), + Person(2, "Julia Smith") + ) ) -docsToInsert.add(ClientNamespacedWriteModel - .insertOne( - MongoNamespace("sample_db", "objects"), - Object(2, "washing machine") - ) +docsToInsert.add( + ClientNamespacedWriteModel + .insertOne( + MongoNamespace("sample_db", "objects"), + Object(2, "washing machine") + ) ) val clientBulkResult = client.bulkWrite(docsToInsert) diff --git a/source/examples/generated/ClientBulkTest.snippet.replace-models.kt b/source/examples/generated/ClientBulkTest.snippet.replace-models.kt index 97bef061..54f95456 100644 --- a/source/examples/generated/ClientBulkTest.snippet.replace-models.kt +++ b/source/examples/generated/ClientBulkTest.snippet.replace-models.kt @@ -1,19 +1,21 @@ val docsReplacements = mutableListOf() -docsReplacements.add(ClientNamespacedWriteModel - .replaceOne( - MongoNamespace("sample_db", "people"), - Filters.eq(Person::id.name, 1), - Person(1, "Frederic Hilbert") - ) +docsReplacements.add( + ClientNamespacedWriteModel + .replaceOne( + MongoNamespace("sample_db", "people"), + Filters.eq(Person::id.name, 1), + Person(1, "Frederic Hilbert") + ) ) -docsReplacements.add(ClientNamespacedWriteModel - .replaceOne( - MongoNamespace("sample_db", "objects"), - Filters.eq(Object::id.name, 1), - Object(1, "ironing board") - ) +docsReplacements.add( + ClientNamespacedWriteModel + .replaceOne( + MongoNamespace("sample_db", "objects"), + Filters.eq(Object::id.name, 1), + Object(1, "ironing board") + ) ) val clientBulkResult = client.bulkWrite(docsReplacements) diff --git a/source/examples/generated/ClientBulkTest.snippet.update-models.kt b/source/examples/generated/ClientBulkTest.snippet.update-models.kt new file mode 100644 index 00000000..b78bafbb --- /dev/null +++ b/source/examples/generated/ClientBulkTest.snippet.update-models.kt @@ -0,0 +1,21 @@ +val docsToInsert = mutableListOf() + +docsToInsert.add( + ClientNamespacedWriteModel + .updateOne( + MongoNamespace("sample_db", "people"), + Filters.eq(Person::name.name, "Freya Polk"), + Updates.inc(Person::age.name, 1) + ) +) + +docsToInsert.add( + ClientNamespacedWriteModel + .updateMany( + MongoNamespace("sample_db", "objects"), + Filters.eq(Object::category.name, "electronic"), + Updates.set(Object::manufacturer.name, "Premium Technologies") + ) +) + +val clientBulkResult = client.bulkWrite(docsToInsert) diff --git a/source/fundamentals/crud/write-operations/bulk.txt b/source/fundamentals/crud/write-operations/bulk.txt index d7ac7536..f3b1cfbb 100644 --- a/source/fundamentals/crud/write-operations/bulk.txt +++ b/source/fundamentals/crud/write-operations/bulk.txt @@ -159,7 +159,7 @@ contains the additional ``location`` field: If multiple documents match the query filter specified in the ``ReplaceOneModel`` instance, the operation replaces the first result. You can specify a sort in a ``ReplaceOptions`` instance to apply -an order to matched documents before the driver performs the replace +an order to matched documents before the server performs the replace operation, as shown in the following code: .. literalinclude:: /examples/generated/BulkTest.snippet.replace-model-options.kt @@ -202,7 +202,7 @@ field by ``1`` in a document where the ``_id`` is ``2``: If multiple documents match the query filter specified in the ``UpdateOneModel`` instance, the operation updates the first result. You can specify a sort in an ``UpdateOptions`` instance to apply -an order to matched documents before the driver performs the update +an order to matched documents before the server performs the update operation, as shown in the following code: .. literalinclude:: /examples/generated/BulkTest.snippet.update-model-options.kt @@ -466,20 +466,65 @@ each write operation applies to. .. literalinclude:: /examples/generated/ClientBulkTest.snippet.insert-models.kt :language: kotlin +.. _kotlin-client-bulk-write-update: + +Update Operation +~~~~~~~~~~~~~~~~ + +The following example shows how to use the ``bulkWrite()`` method to update +existing documents in the ``db.people`` and ``db.objects`` collections: + +.. literalinclude:: /examples/generated/ClientBulkTest.snippet.update-models.kt + :language: kotlin + +This example increments the value of the ``age`` field by ``1`` in the +document that has a ``name`` value of ``"Freya Polk"`` in the ``people`` +collection. It also sets the value of the ``manufacturer`` field to +``"Premium Technologies"`` in all documents that have a ``category`` +value of ``"electronic"`` in the ``objects`` collection. + +If multiple documents match the query filter specified in +a ``ClientNamespacedUpdateOneModel`` instance, the operation updates the +first result. You can specify a sort order in a `ClientUpdateOneOptions +<{+api+}/apidocs/mongodb-driver-core/com/mongodb/client/model/bulk/ClientUpdateOneOptions.html>`__ +instance to apply an order to matched documents before the server +performs the update operation, as shown in the following code: + +.. code-block:: kotlin + + val options = ClientUpdateOneOptions + .clientUpdateOneOptions() + .sort(Sorts.ascending("_id")) + +.. _kotlin-client-bulk-write-replace: + Replace Operation ~~~~~~~~~~~~~~~~~ The following example shows how to use the ``bulkWrite()`` method to replace -existing documents in the ``sample_db.people`` and ``sample_db.things`` collections. +existing documents in the ``sample_db.people`` and ``sample_db.objects`` collections. .. literalinclude:: /examples/generated/ClientBulkTest.snippet.replace-models.kt :language: kotlin After this example runs successfully, the document that has an ``_id`` value of ``1`` in the ``people`` collection is replaced with a new document. The document in -the ``things`` collection that has an ``_id`` value of ``1`` +the ``objects`` collection that has an ``_id`` value of ``1`` is replaced with a new document. +If multiple documents match the query filter specified in +a ``ClientNamespacedReplaceOneModel`` instance, the operation replaces the +first result. You can specify a sort order in a `ClientReplaceOneOptions +<{+api+}/apidocs/mongodb-driver-core/com/mongodb/client/model/bulk/ClientReplaceOneOptions.html>`__ +instance to apply an order to matched documents before the driver +performs the replace operation, as shown in the following code: + +.. code-block:: kotlin + + val options = ClientReplaceOneOptions + .clientReplaceOneOptions() + .sort(Sorts.ascending("_id")) + .. _kotlin-client-bulk-write-options: Bulk Write Options diff --git a/source/fundamentals/transactions.txt b/source/fundamentals/transactions.txt index 2b8d1f35..dd7317ab 100644 --- a/source/fundamentals/transactions.txt +++ b/source/fundamentals/transactions.txt @@ -106,6 +106,13 @@ and commit changes to existing documents: .. sharedinclude:: dbx/transactions-parallelism.rst + .. replacement:: driver-specific-content + + If you're using {+mdb-server+} v8.0 or later, you can perform + write operations on multiple namespaces within a single + transaction by using bulk write operations. To learn more, see the + :ref:`kotlin-fundamentals-bulkwrite` guide. + Additional Information ---------------------- diff --git a/source/whats-new.txt b/source/whats-new.txt index 94c617ac..3cac60d4 100644 --- a/source/whats-new.txt +++ b/source/whats-new.txt @@ -12,6 +12,7 @@ What's New Learn what's new in: +* :ref:`Version 5.4 ` * :ref:`Version 5.3 ` * :ref:`Version 5.2 ` * :ref:`Version 5.1.3 ` @@ -22,6 +23,22 @@ Learn what's new in: * :ref:`Version 4.11 ` * :ref:`Version 4.10 ` +.. _kotlin-coroutine-version-5.4: + +What's New in 5.4 +----------------- + +The 5.4 driver release includes the following changes, fixes, +and features: + +.. sharedinclude:: dbx/jvm/v5.4-wn-items.rst + + .. replacement:: sort-option-link + + the :ref:`kotlin-client-bulk-write-update` and + :ref:`kotlin-client-bulk-write-replace` sections of the Bulk + Operations guide + .. _kotlin-coroutine-version-5.3: What's New in 5.3