From 7b2d2ccce73517c05e0f96f4be8ecc1a14de5110 Mon Sep 17 00:00:00 2001 From: Ben Perlmutter <90647379+mongodben@users.noreply.github.com> Date: Fri, 12 May 2023 10:35:13 -0400 Subject: [PATCH 1/6] fully draft --- examples/src/test/kotlin/FlowTest.kt | 121 +++++++++ .../generated/FlowTest.snippet.count.kt | 2 + .../generated/FlowTest.snippet.explain.kt | 7 + .../generated/FlowTest.snippet.first.kt | 6 + .../generated/FlowTest.snippet.firstOrNull.kt | 2 + .../generated/FlowTest.snippet.iterate.kt | 2 + .../generated/FlowTest.snippet.toList.kt | 2 + source/fundamentals/crud/read-operations.txt | 8 +- .../crud/read-operations/cursor.draft.rst | 242 ------------------ .../crud/read-operations/flow.txt | 130 ++++++++++ 10 files changed, 274 insertions(+), 248 deletions(-) create mode 100644 examples/src/test/kotlin/FlowTest.kt create mode 100644 source/examples/generated/FlowTest.snippet.count.kt create mode 100644 source/examples/generated/FlowTest.snippet.explain.kt create mode 100644 source/examples/generated/FlowTest.snippet.first.kt create mode 100644 source/examples/generated/FlowTest.snippet.firstOrNull.kt create mode 100644 source/examples/generated/FlowTest.snippet.iterate.kt create mode 100644 source/examples/generated/FlowTest.snippet.toList.kt delete mode 100644 source/fundamentals/crud/read-operations/cursor.draft.rst create mode 100644 source/fundamentals/crud/read-operations/flow.txt diff --git a/examples/src/test/kotlin/FlowTest.kt b/examples/src/test/kotlin/FlowTest.kt new file mode 100644 index 00000000..921a00e4 --- /dev/null +++ b/examples/src/test/kotlin/FlowTest.kt @@ -0,0 +1,121 @@ + + +import com.mongodb.ExplainVerbosity +import com.mongodb.kotlin.client.coroutine.MongoClient +import io.github.cdimascio.dotenv.dotenv +import kotlinx.coroutines.flow.* +import kotlinx.coroutines.runBlocking +import org.bson.Document +import org.junit.jupiter.api.AfterAll +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.TestInstance +import java.util.* +import kotlin.test.* + + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +internal class FlowTest { + + data class PaintOrder( + val id: Int, + val color: String, + val qty: Int + ) + companion object { + val dotenv = dotenv() + val client = MongoClient.create(dotenv["MONGODB_CONNECTION_URI"]) + val database = client.getDatabase("paint_store") + val collection = database.getCollection("paint_order") + + @BeforeAll + @JvmStatic + fun beforeAll() { + runBlocking { + collection.insertMany(listOf( + PaintOrder(1, "red", 5), + PaintOrder(2, "purple", 8), + PaintOrder(3, "yellow", 0), + PaintOrder(4, "green", 6), + PaintOrder(5, "pink", 0) + )) + } + } + + @AfterAll + @JvmStatic + fun afterAll() { + runBlocking { + collection.drop() + client.close() + } + } + } + + @Test + fun firstOrNullTest() = runBlocking { + // :snippet-start: firstOrNull + val resultsFlow = collection.find() + val firstResult = resultsFlow.firstOrNull() + // :snippet-end: + assertNotNull(firstResult) + } + @Test + fun firstTest() = runBlocking { + var isReached = false + // :snippet-start: first + try { + val resultsFlow = collection.find() + val firstResult = resultsFlow.first() + isReached = true // :remove: + } catch (e: NoSuchElementException) { + println("No results found") + } + // :snippet-end: + assert(isReached) + } + + @Test + fun countTest() = runBlocking { + // :snippet-start: count + val resultsFlow = collection.find() + val count = resultsFlow.count() + // :snippet-end: + assertEquals(5, count) + } + + @Test + fun toListTest() = runBlocking { + // :snippet-start: toList + val resultsFlow = collection.find() + val results = resultsFlow.toList() + // :snippet-end: + assertEquals(5, results.size) + } + + @Test + fun iterateTest() = runBlocking { + // :snippet-start: iterate + val resultsFlow = collection.find() + resultsFlow.collect { println(it) } + // :snippet-end: + assertEquals(5, resultsFlow.count()) + } + + @Test + fun explainTest() = runBlocking { + // :snippet-start: explain + val explanation = collection.find().explain(ExplainVerbosity.EXECUTION_STATS) + val jsonSummary = explanation.getEmbedded( + listOf("queryPlanner", "winningPlan"), + Document::class.java + ) + .toJson() + println(jsonSummary) + // :snippet-end: + val expected = """{"stage": "COLLSCAN", "direction": "forward"} + """.trimIndent() + assertEquals(expected, jsonSummary) + } +} + diff --git a/source/examples/generated/FlowTest.snippet.count.kt b/source/examples/generated/FlowTest.snippet.count.kt new file mode 100644 index 00000000..072671d8 --- /dev/null +++ b/source/examples/generated/FlowTest.snippet.count.kt @@ -0,0 +1,2 @@ +val resultsFlow = collection.find() +val count = resultsFlow.count() diff --git a/source/examples/generated/FlowTest.snippet.explain.kt b/source/examples/generated/FlowTest.snippet.explain.kt new file mode 100644 index 00000000..449dc9ff --- /dev/null +++ b/source/examples/generated/FlowTest.snippet.explain.kt @@ -0,0 +1,7 @@ +val explanation = collection.find().explain(ExplainVerbosity.EXECUTION_STATS) +val jsonSummary = explanation.getEmbedded( + listOf("queryPlanner", "winningPlan"), + Document::class.java +) + .toJson() +println(jsonSummary) diff --git a/source/examples/generated/FlowTest.snippet.first.kt b/source/examples/generated/FlowTest.snippet.first.kt new file mode 100644 index 00000000..97bd7820 --- /dev/null +++ b/source/examples/generated/FlowTest.snippet.first.kt @@ -0,0 +1,6 @@ +try { + val resultsFlow = collection.find() + val firstResult = resultsFlow.first() +} catch (e: NoSuchElementException) { + println("No results found") +} diff --git a/source/examples/generated/FlowTest.snippet.firstOrNull.kt b/source/examples/generated/FlowTest.snippet.firstOrNull.kt new file mode 100644 index 00000000..08a74618 --- /dev/null +++ b/source/examples/generated/FlowTest.snippet.firstOrNull.kt @@ -0,0 +1,2 @@ +val resultsFlow = collection.find() +val firstResult = resultsFlow.firstOrNull() diff --git a/source/examples/generated/FlowTest.snippet.iterate.kt b/source/examples/generated/FlowTest.snippet.iterate.kt new file mode 100644 index 00000000..13148972 --- /dev/null +++ b/source/examples/generated/FlowTest.snippet.iterate.kt @@ -0,0 +1,2 @@ +val resultsFlow = collection.find() +resultsFlow.collect { println(it) } diff --git a/source/examples/generated/FlowTest.snippet.toList.kt b/source/examples/generated/FlowTest.snippet.toList.kt new file mode 100644 index 00000000..4547241b --- /dev/null +++ b/source/examples/generated/FlowTest.snippet.toList.kt @@ -0,0 +1,2 @@ +val resultsFlow = collection.find() +val results = resultsFlow.toList() diff --git a/source/fundamentals/crud/read-operations.txt b/source/fundamentals/crud/read-operations.txt index 3c13af0b..d2752f8c 100644 --- a/source/fundamentals/crud/read-operations.txt +++ b/source/fundamentals/crud/read-operations.txt @@ -5,6 +5,7 @@ Read Operations .. default-domain:: mongodb - :doc:`/fundamentals/crud/read-operations/retrieve` +- :doc:`/fundamentals/crud/read-operations/flow` - :doc:`/fundamentals/crud/read-operations/change-streams` - :doc:`/fundamentals/crud/read-operations/sort` - :doc:`/fundamentals/crud/read-operations/skip` @@ -13,13 +14,11 @@ Read Operations - :doc:`/fundamentals/crud/read-operations/geo` - :doc:`/fundamentals/crud/read-operations/text` -.. TODO:(DOCSP-29167) add back when refactor cursor page to flow page -.. - :doc:`/fundamentals/crud/read-operations/cursor` - .. toctree:: :caption: Read Operations /fundamentals/crud/read-operations/retrieve + /fundamentals/crud/read-operations/flow /fundamentals/crud/read-operations/change-streams /fundamentals/crud/read-operations/sort /fundamentals/crud/read-operations/skip @@ -27,6 +26,3 @@ Read Operations /fundamentals/crud/read-operations/project /fundamentals/crud/read-operations/geo /fundamentals/crud/read-operations/text - -.. TODO:(DOCSP-29167) add back when refactor cursor page to flow page -.. /fundamentals/crud/read-operations/cursor diff --git a/source/fundamentals/crud/read-operations/cursor.draft.rst b/source/fundamentals/crud/read-operations/cursor.draft.rst deleted file mode 100644 index b0c5323c..00000000 --- a/source/fundamentals/crud/read-operations/cursor.draft.rst +++ /dev/null @@ -1,242 +0,0 @@ -.. _kotlin-fundamentals-cursor: - -========================= -Access Data From a Cursor -========================= - -.. default-domain:: mongodb - -.. contents:: On this page - :local: - :backlinks: none - :depth: 2 - :class: singlecol - -Overview --------- - -In this guide, you can learn how to access data using a **cursor** with the -MongoDB Java driver. - -A cursor is a mechanism that allows an application to iterate over database -results while only holding a subset of them in memory at a given time. The -driver uses cursors in read operations that match multiple documents to return -matched documents in batches as opposed to returning them all at once. - -This page uses an initiating method, ``find()`` to show how to access -data from a `FindIterable -<{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/FindIterable.html>`__. - -.. note:: - - The following ways to access and store data apply to - other iterables such as an `AggregateIterable - <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/AggregateIterable.html>`__. - -The ``find()`` method creates and returns an instance of a -``FindIterable``. A ``FindIterable`` allows you to browse the documents -matched by your search criteria and to further specify which documents -to see by setting parameters through methods. - -Terminal Methods ----------------- - -Terminal methods execute an operation on the MongoDB server after -configuring all parameters of an ``Iterable`` instance controlling the -operation. - -First -~~~~~ - -Use the ``first()`` method to retrieve the first document in your query -results: - -.. literalinclude:: /includes/fundamentals/code-snippets/Cursor.java - :language: java - :dedent: - :start-after: begin firstExample - :end-before: end firstExample - -This method is often used when your query filter will match one -document, such as when filtering by a unique index. - -Number of Results -~~~~~~~~~~~~~~~~~ - -Use the ``available()`` method to retrieve the number of results -locally present without blocking: - -.. literalinclude:: /includes/fundamentals/code-snippets/Cursor.java - :language: java - :dedent: - :start-after: begin availableExample - :end-before: end availableExample - -The method returns ``0`` if the application has already iterated though -all the documents in the cursor or if the cursor is closed. - -Into -~~~~ - -Use the ``into()`` method to store your query results in a ``List``: - -.. literalinclude:: /includes/fundamentals/code-snippets/Cursor.java - :language: java - :dedent: - :start-after: begin intoExample - :end-before: end intoExample - -This method is often used when your query filter returns a small number -of documents that can fit into available memory. - -Cursor -~~~~~~ - -Use the ``cursor()`` method to iterate through fetched documents and -ensure that the cursor closes if there is an early termination: - -.. code-block:: java - :copyable: true - - MongoCursor cursor = collection.find().cursor(); - -For more information on how to ensure a cursor closes, see the :ref:`cursor cleanup section `. - -Explain -~~~~~~~ - -Use the ``explain()`` method to view information about how MongoDB -executes your operation. - -The ``explain()`` method returns **execution plans** and performance -statistics. An execution plan is a potential way MongoDB -can complete an operation. The ``explain()`` method provides both the -winning plan (the plan MongoDB executed) and rejected plans. - -.. include:: /includes/fundamentals/explain-verbosity.rst - -The following example prints the JSON representation of the -winning plan for aggregation stages that produce execution plans: - -.. literalinclude:: /includes/fundamentals/code-snippets/Cursor.java - :language: java - :dedent: - :start-after: begin explainExample - :end-before: end explainExample - -The preceding code snippet should produce the following output: - -.. code-block:: none - :copyable: false - - { "stage": "COLLSCAN", "direction": "forward" } - -For more information on the explain operation, see the following -Server Manual Entries: - -- :manual:`Explain Output ` -- :manual:`Query Plans ` - -For more information about the methods and classes mentioned in this section, -see the following API Documentation: - -- `first() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoIterable.html#first()>`__ -- `available() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCursor.html#available()>`__ -- `into() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoIterable.html#into(A)>`__ -- `cursor() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoIterable.html#cursor()>`__ -- `explain() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/FindIterable.html#explain()>`__ -- `ExplainVerbosity <{+api+}/apidocs/mongodb-driver-core/com/mongodb/ExplainVerbosity>`__ - -Usage Patterns --------------- - -A ``MongoCursor`` and ``FindIterable`` allow you to access query results -one document at a time, abstracting away network and caching logic. - -Functional Iteration -~~~~~~~~~~~~~~~~~~~~~ - -Pass a function to the ``forEach()`` method of a ``FindIterable`` to -iterate through results in a functional style: - -.. literalinclude:: /includes/fundamentals/code-snippets/Cursor.java - :language: java - :dedent: - :start-after: begin forEachIteration - :end-before: end forEachIteration - -.. important:: - - Initiating methods return objects that implement the ``Iterable`` interface which allows you - to iterate through them using iterator methods. Sometimes, we use an enhanced - for-each loop to iterate through results: - - .. code-block:: java - - for (Document cur : collection.find()) { - ... - } - - Iterating this way is not preferable because if an exception is - thrown before the loop completes, the cursor will not close. Using a - ``MongoCursor`` allows us to ensure the cursor closes as shown in the - :ref:`cursor cleanup section `. - -.. _kotlin-fundamentals-cursor-conditional-iteration: - -Conditional Iteration -~~~~~~~~~~~~~~~~~~~~~ - -Use the ``hasNext()`` method to check if there are any documents -available in the cursor, and then use the ``next()`` method to retrieve -the next available document from the cursor: - -.. literalinclude:: /includes/fundamentals/code-snippets/Cursor.java - :language: java - :dedent: - :start-after: begin manualIteration - :end-before: end manualIteration - -For more information about the methods and classes mentioned in this section, -see the following API Documentation: - -- `forEach() `__ -- `hasNext() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCursor.html#hasNext()>`__ -- `next() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCursor.html#next()>`__ - -.. _cursor_cleanup: - -Cursor Cleanup --------------- - -Close -~~~~~ - -Use the ``close()`` method in a finally block to free up a cursor's -consumption of resources in both the client application and the MongoDB -server: - -.. literalinclude:: /includes/fundamentals/code-snippets/Cursor.java - :language: java - :dedent: - :start-after: begin closeExample - :end-before: end closeExample - -Try with Resources Statement -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Use a try-with-resources statement -to automatically free up a cursor's consumption of resources in both the -client application and the MongoDB server: - -.. literalinclude:: /includes/fundamentals/code-snippets/Cursor.java - :language: java - :dedent: - :start-after: begin tryWithResourcesExample - :end-before: end tryWithResourcesExample - -For more information about the methods and classes mentioned in this section, -see the following API Documentation: - -- `close() <{+api+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCursor.html#close()>`__ -- `try-with-resources statement `__ diff --git a/source/fundamentals/crud/read-operations/flow.txt b/source/fundamentals/crud/read-operations/flow.txt new file mode 100644 index 00000000..01207561 --- /dev/null +++ b/source/fundamentals/crud/read-operations/flow.txt @@ -0,0 +1,130 @@ +.. _kotlin-fundamentals-cursor: + +========================= +Access Data From a Cursor +========================= + +.. default-domain:: mongodb + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +Overview +-------- + +In this guide, you can learn how to access data using a ``Flow`` with the +MongoDB Kotlin driver. + +A ``Flow`` is a data type built into Kotlin coroutines that represent a stream +of values that are being computed asynchronously. The Kotlin coroutine driver +uses flows to represent the results of database read operations. + +This page uses an initiating method, ``find()`` to show how to access +data from a `FindFlow +<{+api-kotlin+}/apidocs/mongodb-driver-kotlin-coroutine/mongodb-driver-kotlin-coroutine/com.mongodb.kotlin.client.coroutine/-find-flow/index.html>`__. + +.. note:: + + The following ways to access and store data apply to + other iterables such as an `AggregateFlow + <{+api-kotlin+}/apidocs/mongodb-driver-kotlin-coroutine/mongodb-driver-kotlin-coroutine/com.mongodb.kotlin.client.coroutine/-aggregate-flow/index.html>`__. + +The ``find()`` method creates and returns an instance of a +``FindFlow``. A ``FindFlow`` allows you to browse the documents +matched by your search criteria and to further specify which documents +to see by setting parameters through methods. + +Terminal Methods +---------------- + +Terminal methods execute an operation on the MongoDB server after +configuring all parameters of a ``Flow`` instance controlling the +operation. + +Find the First Document +~~~~~~~~~~~~~~~~~~~~~~~ + +Use the ``firstOrNull()`` method to retrieve the first document in your query +results or ``null`` if there are no results: + +.. literalinclude:: /examples/generated/FlowTest.snippet.firstOrNull.kt + :language: kotlin + +Alternatively, you can use the ``first()`` method to retrieve the first document +in your query or throw a ``NoSuchElementException`` if there are no results: + +.. literalinclude:: /examples/generated/FlowTest.snippet.first.kt + :language: kotlin + +These methods are often used when your query filter will match one +document, such as when filtering by a unique index. + +Count Number of Results +~~~~~~~~~~~~~~~~~~~~~~~ + +Use the ``count()`` method to retrieve the number of results in the query: + +.. literalinclude:: /examples/generated/FlowTest.snippet.count.kt + :language: kotlin + +Convert Results to a List +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Use the ``toList()`` method to store your query results in a ``List``: + +.. literalinclude:: /examples/generated/FlowTest.snippet.toList.kt + :language: kotlin + +This method is often used when your query filter returns a small number +of documents that can fit into available memory. + +Iterate through Results +~~~~~~~~~~~~~~~~~~~~~~~ + +Use the ``collect()`` method to iterate through fetched documents and +ensure that the flow closes if there is an early termination: + +.. literalinclude:: /examples/generated/FlowTest.snippet.iterate.kt + :language: kotlin + +Explain the Query +~~~~~~~~~~~~~~~~~ + +Use the ``explain()`` method to view information about how MongoDB +executes your operation. + +The ``explain()`` method returns **execution plans** and performance +statistics. An execution plan is a potential way MongoDB +can complete an operation. The ``explain()`` method provides both the +winning plan (the plan MongoDB executed) and rejected plans. + +.. include:: /includes/fundamentals/explain-verbosity.rst + +The following example prints the JSON representation of the +winning plan for aggregation stages that produce execution plans: + +.. io-code-block:: + + .. input:: /examples/generated/FlowTest.snippet.explain.kt + :language: kotlin + + .. output:: + :language: json + + { "stage": "COLLSCAN", "direction": "forward" } + +For more information on the explain operation, see the following +Server Manual Entries: + +- :manual:`Explain Output ` +- :manual:`Query Plans ` + +For more information about the methods and classes mentioned in this section, +see the following API Documentation: + +- `collect() <{+api-kotlin+}/apidocs/mongodb-driver-kotlin-coroutine/mongodb-driver-kotlin-coroutine/com.mongodb.kotlin.client.coroutine/-find-flow/collect.html>`__ +- `explain() <{+api-kotlin+}/apidocs/mongodb-driver-kotlin-coroutine/mongodb-driver-kotlin-coroutine/com.mongodb.kotlin.client.coroutine/-find-flow/explain.html>`__ +- `ExplainVerbosity <{+api+}/apidocs/mongodb-driver-core/com/mongodb/ExplainVerbosity>`__ From 746b87ff310e93221cba76adfeec813891a0c496 Mon Sep 17 00:00:00 2001 From: Ben Perlmutter <90647379+mongodben@users.noreply.github.com> Date: Fri, 12 May 2023 10:38:51 -0400 Subject: [PATCH 2/6] update title --- source/fundamentals/crud/read-operations/flow.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/fundamentals/crud/read-operations/flow.txt b/source/fundamentals/crud/read-operations/flow.txt index 01207561..cce314a7 100644 --- a/source/fundamentals/crud/read-operations/flow.txt +++ b/source/fundamentals/crud/read-operations/flow.txt @@ -1,8 +1,8 @@ .. _kotlin-fundamentals-cursor: -========================= -Access Data From a Cursor -========================= +======================= +Access Data From a Flow +======================= .. default-domain:: mongodb From aa035765ed7aaf2088d2172a7ae22c0400c91615 Mon Sep 17 00:00:00 2001 From: Ben Perlmutter <90647379+mongodben@users.noreply.github.com> Date: Fri, 12 May 2023 10:43:10 -0400 Subject: [PATCH 3/6] copy edit --- examples/src/test/kotlin/FlowTest.kt | 4 ++-- source/examples/generated/FlowTest.snippet.firstOrNull.kt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/src/test/kotlin/FlowTest.kt b/examples/src/test/kotlin/FlowTest.kt index 921a00e4..1852f923 100644 --- a/examples/src/test/kotlin/FlowTest.kt +++ b/examples/src/test/kotlin/FlowTest.kt @@ -56,9 +56,9 @@ internal class FlowTest { fun firstOrNullTest() = runBlocking { // :snippet-start: firstOrNull val resultsFlow = collection.find() - val firstResult = resultsFlow.firstOrNull() + val firstResultOrNull = resultsFlow.firstOrNull() // :snippet-end: - assertNotNull(firstResult) + assertNotNull(firstResultOrNull) } @Test fun firstTest() = runBlocking { diff --git a/source/examples/generated/FlowTest.snippet.firstOrNull.kt b/source/examples/generated/FlowTest.snippet.firstOrNull.kt index 08a74618..80630557 100644 --- a/source/examples/generated/FlowTest.snippet.firstOrNull.kt +++ b/source/examples/generated/FlowTest.snippet.firstOrNull.kt @@ -1,2 +1,2 @@ val resultsFlow = collection.find() -val firstResult = resultsFlow.firstOrNull() +val firstResultOrNull = resultsFlow.firstOrNull() From 94e91a3934aaa4bf1bd2d29ed73e17cabe806d81 Mon Sep 17 00:00:00 2001 From: Ben Perlmutter <90647379+mongodben@users.noreply.github.com> Date: Fri, 12 May 2023 10:44:46 -0400 Subject: [PATCH 4/6] copy edit --- examples/src/test/kotlin/FlowTest.kt | 3 +-- source/examples/generated/FlowTest.snippet.explain.kt | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/examples/src/test/kotlin/FlowTest.kt b/examples/src/test/kotlin/FlowTest.kt index 1852f923..1e761f6b 100644 --- a/examples/src/test/kotlin/FlowTest.kt +++ b/examples/src/test/kotlin/FlowTest.kt @@ -109,8 +109,7 @@ internal class FlowTest { val jsonSummary = explanation.getEmbedded( listOf("queryPlanner", "winningPlan"), Document::class.java - ) - .toJson() + ).toJson() println(jsonSummary) // :snippet-end: val expected = """{"stage": "COLLSCAN", "direction": "forward"} diff --git a/source/examples/generated/FlowTest.snippet.explain.kt b/source/examples/generated/FlowTest.snippet.explain.kt index 449dc9ff..66e10ccf 100644 --- a/source/examples/generated/FlowTest.snippet.explain.kt +++ b/source/examples/generated/FlowTest.snippet.explain.kt @@ -2,6 +2,5 @@ val explanation = collection.find().explain(ExplainVerbosity.EXECUTION_STATS) val jsonSummary = explanation.getEmbedded( listOf("queryPlanner", "winningPlan"), Document::class.java -) - .toJson() +).toJson() println(jsonSummary) From 61aeff1e017acc34e6912c697eb79b9bf97acf8b Mon Sep 17 00:00:00 2001 From: Ben Perlmutter <90647379+mongodben@users.noreply.github.com> Date: Fri, 12 May 2023 10:49:14 -0400 Subject: [PATCH 5/6] update ref --- source/fundamentals/crud/read-operations/flow.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/fundamentals/crud/read-operations/flow.txt b/source/fundamentals/crud/read-operations/flow.txt index cce314a7..9a5e3e69 100644 --- a/source/fundamentals/crud/read-operations/flow.txt +++ b/source/fundamentals/crud/read-operations/flow.txt @@ -1,4 +1,4 @@ -.. _kotlin-fundamentals-cursor: +.. _kotlin-fundamentals-flow: ======================= Access Data From a Flow From 90e7fe4716dbad1fb50a5917a77e3512ef5db17e Mon Sep 17 00:00:00 2001 From: cbullinger <115956901+cbullinger@users.noreply.github.com> Date: Tue, 13 Jun 2023 08:24:10 -0400 Subject: [PATCH 6/6] Update with flow delegation and address TODOs --- examples/src/test/kotlin/FlowTest.kt | 6 +-- examples/src/test/kotlin/TimeSeriesTest.kt | 6 +-- .../crud/read-operations/flow.txt | 2 - source/quick-reference.txt | 37 +++++++++---------- source/usage-examples/distinct.txt | 11 +++--- source/usage-examples/find.txt | 11 ++---- source/usage-examples/findOne.txt | 11 ++---- 7 files changed, 36 insertions(+), 48 deletions(-) diff --git a/examples/src/test/kotlin/FlowTest.kt b/examples/src/test/kotlin/FlowTest.kt index 1e761f6b..96ab7649 100644 --- a/examples/src/test/kotlin/FlowTest.kt +++ b/examples/src/test/kotlin/FlowTest.kt @@ -2,7 +2,7 @@ import com.mongodb.ExplainVerbosity import com.mongodb.kotlin.client.coroutine.MongoClient -import io.github.cdimascio.dotenv.dotenv +import config.getConfig import kotlinx.coroutines.flow.* import kotlinx.coroutines.runBlocking import org.bson.Document @@ -23,8 +23,8 @@ internal class FlowTest { val qty: Int ) companion object { - val dotenv = dotenv() - val client = MongoClient.create(dotenv["MONGODB_CONNECTION_URI"]) + val config = getConfig() + val client = MongoClient.create(config.connectionUri) val database = client.getDatabase("paint_store") val collection = database.getCollection("paint_order") diff --git a/examples/src/test/kotlin/TimeSeriesTest.kt b/examples/src/test/kotlin/TimeSeriesTest.kt index ce4c0ec5..23e49cf4 100644 --- a/examples/src/test/kotlin/TimeSeriesTest.kt +++ b/examples/src/test/kotlin/TimeSeriesTest.kt @@ -5,7 +5,7 @@ import com.mongodb.client.model.Filters.* import com.mongodb.client.model.Projections.* import com.mongodb.client.model.TimeSeriesOptions import com.mongodb.kotlin.client.coroutine.MongoClient -import io.github.cdimascio.dotenv.dotenv +import config.getConfig import kotlinx.coroutines.flow.toList import kotlinx.coroutines.runBlocking import org.bson.json.JsonWriterSettings @@ -20,8 +20,8 @@ import kotlin.test.* internal class TimeSeriesTest { companion object { - val dotenv = dotenv() - val mongoClient = MongoClient.create(dotenv["MONGODB_CONNECTION_URI"]) + val config = getConfig() + val mongoClient = MongoClient.create(config.connectionUri) @AfterAll @JvmStatic diff --git a/source/fundamentals/crud/read-operations/flow.txt b/source/fundamentals/crud/read-operations/flow.txt index 9a5e3e69..6287a0b5 100644 --- a/source/fundamentals/crud/read-operations/flow.txt +++ b/source/fundamentals/crud/read-operations/flow.txt @@ -4,8 +4,6 @@ Access Data From a Flow ======================= -.. default-domain:: mongodb - .. contents:: On this page :local: :backlinks: none diff --git a/source/quick-reference.txt b/source/quick-reference.txt index 0aaf453a..f45087d5 100644 --- a/source/quick-reference.txt +++ b/source/quick-reference.txt @@ -4,8 +4,6 @@ Quick Reference =============== -.. default-domain:: mongodb - This page shows the driver syntax for several MongoDB commands and links to their related reference and API documentation. @@ -350,21 +348,20 @@ The examples on the page use the following data class to represent MongoDB docum - .. include:: /includes/kotlin-driver-coroutine-gradle-versioned.rst -.. TODO:(DOCSP-29167) add back as part of this ticket. needs refactoring b/c cursor not thing for coroutines driver -.. * - | **Access Data from a Flow Iteratively** -.. | -.. | `API Documentation <{+api-kotlin+}/apidocs/mongodb-driver-sync/com/mongodb/client/MongoCursor.html>`__ -.. | :ref:`Fundamentals ` -.. - .. io-code-block:: -.. :copyable: true -.. .. input:: -.. :language: kotlin -.. .. output:: -.. :language: console - :visible: false -.. -.. [ -.. { title: '2001: A Space Odyssey', ... }, -.. { title: 'The Sound of Music', ... }, -.. ... -.. ] + * - | **Access Data from a Flow Iteratively** + | + | `API Documentation <{+api-kotlin+}/apidocs/mongodb-driver-kotlin-coroutine/mongodb-driver-kotlin-coroutine/com.mongodb.kotlin.client.coroutine/-find-flow/index.html>`__ + | :ref:`Fundamentals ` + + - .. io-code-block:: + :copyable: true + + .. input:: /examples/generated/FlowTest.snippet.iterate.kt + :language: kotlin + + .. output:: + :language: console + :visible: false + + Movie(title=2001: A Space Odyssey, ...) + Movie(title=The Sound of Music, ...) diff --git a/source/usage-examples/distinct.txt b/source/usage-examples/distinct.txt index 599f2340..519adb10 100644 --- a/source/usage-examples/distinct.txt +++ b/source/usage-examples/distinct.txt @@ -38,14 +38,13 @@ distinct values with a query filter as a second parameter, as follows: :language: kotlin The ``distinct()`` method returns an object that implements the -``DistinctFlow`` class, which contains methods to access,organize, and traverse -the results. ``DistinctFlow`` also inherits methods from its parent class -``Flow`` from the Kotlin Coroutines library, such as ``first()`` and +``DistinctFlow`` class, which contains methods to access, organize, and traverse +the results. ``DistinctFlow`` delegates to the ``Flow`` interface +from the Kotlin Coroutines library, allowing access to methods such as ``first()`` and ``firstOrNull()``. -.. TODO (DOCSP-29176) Add link to Flow documentation when available -.. For more information, see our -.. :doc:`guide on Accessing Data From a Flow `. +For more information, see our +:doc:`guide on Accessing Data From a Flow `. Example ------- diff --git a/source/usage-examples/find.txt b/source/usage-examples/find.txt index 1325efd8..06acbee4 100644 --- a/source/usage-examples/find.txt +++ b/source/usage-examples/find.txt @@ -28,19 +28,16 @@ For more information on the ``projection()`` method, see our The ``find()`` method returns an instance of ``FindFlow``, a class that offers several methods to access, organize, and traverse the results. -.. TODO (DOCSP-29176) Update with accurate inheritance information when available -.. ``FindFlow`` also inherits methods from its parent class ``Flow`` from the -.. Kotlin Coroutines library. - +``FindFlow`` also obtains methods from its delegate interface ``Flow`` from the +Kotlin Coroutines library. You can call the ``collect()`` method to iterate through the fetched results. You can also call terminal methods, such as ``firstOrNull()`` to return either the first document or ``null`` if there are no results, or ``first()`` to return the first document in the collection. If no documents match the query, calling ``first()`` throws a ``NoSuchElementException`` exception. -.. TODO (DOCSP-29176) Add link to Flow documentation when available -.. For more information on accessing data from a flow with the Kotlin driver, see our -.. :doc:`guide on Accessing Data From a Flow `. +For more information on accessing data from a flow with the Kotlin driver, see our +:doc:`guide on Accessing Data From a Flow `. Example ------- diff --git a/source/usage-examples/findOne.txt b/source/usage-examples/findOne.txt index a595de03..b466ace9 100644 --- a/source/usage-examples/findOne.txt +++ b/source/usage-examples/findOne.txt @@ -27,18 +27,15 @@ For more information on the ``projection()`` method, see our The ``find()`` method returns an instance of ``FindFlow``, a class that offers several methods to access, organize, and traverse the results. -.. TODO (DOCSP-29176) Update with accurate inheritance information when available -.. ``FindFlow`` also inherits methods from its parent class ``Flow`` from the -.. Kotlin Coroutines library, such as ``first()`` and ``firstOrNull()``. - +``FindFlow`` also obtains methods from its delegate interface ``Flow`` from the +Kotlin Coroutines library, such as ``first()`` and ``firstOrNull()``. The ``firstOrNull()`` method returns the first document from the retrieved results or ``null`` if there are no results. The ``first()`` method returns the first document or throws a ``NoSuchElementException`` exception if no documents match the query. -.. TODO (DOCSP-29176) Add link to Flow documentation when available -.. For more information on accessing data from a flow with the Kotlin driver, see our -.. :doc:`guide on Accessing Data From a Flow `. +For more information on accessing data from a flow with the Kotlin driver, see our +:doc:`guide on Accessing Data From a Flow `. Example -------