diff --git a/snooty.toml b/snooty.toml index 80b26c61..f9c4ddeb 100644 --- a/snooty.toml +++ b/snooty.toml @@ -24,6 +24,7 @@ sharedinclude_root = "https://raw.githubusercontent.com/10gen/docs-shared/main/" [constants] driver-short = "PyMongo" driver-long = "PyMongo, the MongoDB synchronous Python driver," +driver-async = "PyMongo Async" language = "Python" mdb-server = "MongoDB Server" mongo-community = "MongoDB Community Edition" diff --git a/source/connect/stable-api.txt b/source/connect/stable-api.txt index 5289fc05..c6ef8b3c 100644 --- a/source/connect/stable-api.txt +++ b/source/connect/stable-api.txt @@ -120,4 +120,3 @@ following API documentation: - `MongoClient <{+api-root+}pymongo/mongo_client.html#pymongo.mongo_client.MongoClient>`__ - `ServerApi <{+api-root+}pymongo/server_api.html#pymongo.server_api.ServerApi>`__ - `ServerApiVersion <{+api-root+}pymongo/server_api.html#pymongo.server_api.ServerApiVersion>`__ - diff --git a/source/includes/pymongo-async-experimental.rst b/source/includes/pymongo-async-experimental.rst new file mode 100644 index 00000000..4d332cfe --- /dev/null +++ b/source/includes/pymongo-async-experimental.rst @@ -0,0 +1,7 @@ +.. important:: + + The {+driver-async+} driver is experimental and should not be used in + production environments. Classes, methods, and behaviors described in this + guide might change prior to the full release. If you encounter any + issues with {+driver-async+}, you can learn how to report them on the + :ref:`pymongo-issues-help` page. \ No newline at end of file diff --git a/source/index.txt b/source/index.txt index 5c5f7cee..fb4565c4 100644 --- a/source/index.txt +++ b/source/index.txt @@ -26,6 +26,8 @@ MongoDB {+driver-short+} Documentation /troubleshooting /whats-new /upgrade + /motor-async-migration + /pymongo-to-async-guide /previous-versions /issues-and-help /compatibility @@ -120,6 +122,21 @@ Upgrade {+driver-short+} Versions Learn what changes you might need to make to your application to upgrade driver versions in the :ref:`pymongo-upgrade` section. +Migrate from Motor to {+driver-async+} +------------------------------------- + +In September 2024, MongoDB released the experimental {+driver-async+} driver as a replacement +for `Motor `__, the previous asynchronous +MongoDB driver for Python. Learn how to migrate from Motor +to the {+driver-async+} driver in the :ref:`pymongo-async-motor-migration` +section. + +Switch from {+driver-short+} to {+driver-async+} +---------------------------------------------- + +Learn what changes you need to make to switch from {+driver-short+} to +the experimental {+driver-async+} driver in the :ref:`pymongo-to-async-guide` section. + Previous Versions ----------------- diff --git a/source/motor-async-migration.txt b/source/motor-async-migration.txt new file mode 100644 index 00000000..ff15fe70 --- /dev/null +++ b/source/motor-async-migration.txt @@ -0,0 +1,76 @@ +.. _pymongo-async-motor-migration: + +==================================== +Migrate from Motor to {+driver-async+} +==================================== + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +.. facet:: + :name: genre + :values: reference + +.. meta:: + :keywords: motor, async, refactor, migration + +.. include:: /includes/pymongo-async-experimental.rst + +Overview +-------- + +The {+driver-async+} driver is a unification of {+driver-short+} and the `Motor +library `__. In this guide, you can +identify the changes you must make to migrate an application from +Motor to the {+driver-async+} driver. + +Migrate From Motor +------------------ + +The {+driver-async+} driver functions similarly to the Motor library, but allows +for improved latency and throughput due to directly using Python Asyncio instead +of delegating work to a thread pool. In most cases, you can directly migrate +existing Motor applications to {+driver-async+} by using ``AsyncMongoClient`` in +place of ``MotorClient``, and changing the application's import statements to +import from ``pymongo``. + +The following example shows the difference in imports to use a client for +read and write operations in Motor compared to {+driver-async+}: + +.. code-block:: python + + # Motor client import + from motor.motor_asyncio import AsyncIOMotorClient + + # {+driver-async+} client import + from pymongo import AsyncMongoClient + +To see a list of the asynchronous methods available in the {+driver-async+} +driver, see the :ref:`pymongo-async-methods` section in the {+driver-short+} to +{+driver-async+} guide. + +The following section shows the method signature changes that you must implement +in your application when migrating from Motor to the {+driver-async+} driver. + +Method Signature Changes +~~~~~~~~~~~~~~~~~~~~~~~~ + +The following Motor method signatures behave differently in the {+driver-async+} driver: + +- ``AsyncMongoClient.__init__()`` does not accept an ``io_loop`` parameter. +- ``AsyncCursor.each()`` does not exist in the {+driver-async+} driver. +- ``MotorGridOut.stream_to_handler()`` does not exist in the {+driver-async+} driver. +- ``AsyncCursor.to_list(0)`` is not valid in the {+driver-async+} driver. Use + ``to_list(None)`` instead. +- ``MongoClient`` is thread safe and can be used by many threads, however, an + ``AsyncMongoClient`` is not thread safe and should only be used by a single + event loop. + +Additional Information +---------------------- + +To learn more about asynchronous Python, see the `Python Asyncio documentation +`__. \ No newline at end of file diff --git a/source/pymongo-to-async-guide.txt b/source/pymongo-to-async-guide.txt new file mode 100644 index 00000000..27b1dbea --- /dev/null +++ b/source/pymongo-to-async-guide.txt @@ -0,0 +1,330 @@ +.. _pymongo-to-async-guide: + +==================================== +Switch from {+driver-short+} to {+driver-async+} +==================================== + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +.. facet:: + :name: genre + :values: reference + +.. meta:: + :keywords: asyncronous, refactor, migration + +.. include:: /includes/pymongo-async-experimental.rst + +Overview +-------- + +The {+driver-async+} driver is a unification of {+driver-short+} and the `Motor +library `__. In this guide, you can +identify the changes you must make to switch from {+driver-short+} to +{+driver-async+}. + +Switch From {+driver-short+} +------------------- + +The {+driver-async+} driver behaves similarly to {+driver-short+}, but +all methods that perform network operations are coroutines and must be awaited. +To switch from {+driver-short+} to {+driver-async+}, you must update your code +in the following ways: + +- Replace all uses of ``MongoClient`` with ``AsyncMongoClient``. +- Add the ``await`` keyword to all asynchronous method calls. +- If you call an asynchronous method inside of a function, mark the function as ``async``. + +The following sections describe how to implement the asynchronous API. + +.. _pymongo-async-methods: + +Asynchronous Methods +~~~~~~~~~~~~~~~~~~~~ + +The following tables list the asynchronous methods that are available in the +{+driver-async+} driver. To call these methods, you must ``await`` them and call them +inside an ``async`` function. + +Client Methods +`````````````` + +.. list-table:: + :header-rows: 1 + :widths: 20 80 + + * - Method + - Example + + * - ``AsyncMongoClient()`` + - .. code-block:: python + + from pymongo import AsyncMongoClient + + async with AsyncMongoClient(...) + + * - ``watch()`` + - .. code-block:: python + + async with await client.watch(...) as stream: + ... + + * - ``server_info()`` + - .. code-block:: python + + await client.server_info(...) + + * - ``list_databases()`` + - .. code-block:: python + + await client.list_databases() + + * - ``list_database_names()`` + - .. code-block:: python + + await client.list_database_names() + + * - ``drop_database()`` + - .. code-block:: python + + await client.drop_database(...) + +Database Methods +```````````````` + +.. list-table:: + :header-rows: 1 + :widths: 20 80 + + * - Method + - Example + + * - ``watch()`` + - .. code-block:: python + + async with await db.watch(...) as stream: + ... + + * - ``create_collection()`` + - .. code-block:: python + + await db.create_collection(...) + + * - ``aggregate()`` + - .. code-block:: python + + async with await client.admin.aggregate(...) as cursor: + ... + + * - ``command()`` + - .. code-block:: python + + await db.command(...) + + * - ``cursor_command()`` + - .. code-block:: python + + await db.cursor_command(...) + + * - ``list_collections()`` + - .. code-block:: python + + await db.list_collections() + + * - ``list_collection_names()`` + - .. code-block:: python + + await db.list_collection_names() + + * - ``drop_collection()`` + - .. code-block:: python + + await db.drop_collection(...) + + * - ``validate_collection()`` + - .. code-block:: python + + await db.validate_collection(...) + + * - ``dereference()`` + - .. code-block:: python + + await db.dereference(...) + +Collection Methods +`````````````````` + +.. list-table:: + :header-rows: 1 + :widths: 20 80 + + * - Method + - Example + + * - ``watch()`` + - .. code-block:: python + + async with await collection.watch(...) as stream: + ... + + * - ``insert_one()`` + - .. code-block:: python + + await collection.insert_one(...) + + * - ``insert_many()`` + - .. code-block:: python + + await collection.insert_many(...) + + * - ``replace_one()`` + - .. code-block:: python + + await collection.replace_one(...) + + * - ``update_one()`` + - .. code-block:: python + + await collection.update_one(...) + + * - ``update_many()`` + - .. code-block:: python + + await collection.update_many(...) + + * - ``drop()`` + - .. code-block:: python + + await collection.drop() + + * - ``delete_one()`` + - .. code-block:: python + + await collection.delete_one(...) + + * - ``delete_many()`` + - .. code-block:: python + + await collection.delete_many(...) + + * - ``find_one()`` + - .. code-block:: python + + await collection.find_one(...) + + * - ``estimated_document_count()`` + - .. code-block:: python + + await collection.estimated_document_count() + + * - ``count_documents()`` + - .. code-block:: python + + await collection.count_documents(...) + + * - ``create_index()`` + - .. code-block:: python + + await collection.create_index(...) + + * - ``create_indexes()`` + - .. code-block:: python + + await collection.create_indexes(...) + + * - ``drop_index()`` + - .. code-block:: python + + await collection.drop_index(...) + + * - ``drop_indexes()`` + - .. code-block:: python + + await collection.drop_indexes() + + * - ``list_indexes()`` + - .. code-block:: python + + await collection.list_indexes() + + * - ``index_information()`` + - .. code-block:: python + + await collection.index_information() + + * - ``list_search_indexes()`` + - .. code-block:: python + + await collection.list_search_indexes() + + * - ``create_search_index()`` + - .. code-block:: python + + await collection.create_search_index(...) + + * - ``create_search_indexes()`` + - .. code-block:: python + + await collection.create_search_indexes(...) + + * - ``drop_search_index()`` + - .. code-block:: python + + await collection.drop_search_index(...) + + * - ``update_search_index()`` + - .. code-block:: python + + await collection.update_search_index(...) + + * - ``options()`` + - .. code-block:: python + + await collection.options() + + * - ``aggregate()`` + - .. code-block:: python + + async for doc in await collection.aggregate(...): + ... + + * - ``aggregate_raw_batches()`` + - .. code-block:: python + + async for batch in await collection.aggregate_raw_batches(...): + ... + + * - ``rename()`` + - .. code-block:: python + + await collection.rename(...) + + * - ``distinct()`` + - .. code-block:: python + + await collection.distinct(...) + + * - ``find_one_and_delete()`` + - .. code-block:: python + + await collection.find_one_and_delete(...) + + * - ``find_one_and_replace()`` + - .. code-block:: python + + await collection.find_one_and_replace(...) + + * - ``find_one_and_update()`` + - .. code-block:: python + + await collection.find_one_and_update(...) + +Additional Information +---------------------- + +To learn more about asynchronous Python, see the `Python Asyncio documentation +`__. \ No newline at end of file