diff --git a/source/includes/write/bulk-write.py b/source/includes/write/bulk-write.py index 509d6cf3..82793cf7 100644 --- a/source/includes/write/bulk-write.py +++ b/source/includes/write/bulk-write.py @@ -1,6 +1,7 @@ # start-bulk-insert-one -operation = pymongo.InsertOne( - { +operation = InsertOne( + namespace="sample_restaurants.restaurants", + document={ "name": "Mongo's Deli", "cuisine": "Sandwiches", "borough": "Manhattan", @@ -10,23 +11,26 @@ # end-bulk-insert-one # start-bulk-update-one -operation = pymongo.UpdateOne( - { "name": "Mongo's Deli" }, - { "$set": { "cuisine": "Sandwiches and Salads" }}, +operation = UpdateOne( + namespace="sample_restaurants.restaurants", + filter={ "name": "Mongo's Deli" }, + update={ "$set": { "cuisine": "Sandwiches and Salads" }} ) # end-bulk-update-one # start-bulk-update-many -operation = pymongo.UpdateMany( - { "name": "Mongo's Deli" }, - { "$set": { "cuisine": "Sandwiches and Salads" }}, +operation = UpdateMany( + namespace="sample_restaurants.restaurants", + filter={ "name": "Mongo's Deli" }, + update={ "$set": { "cuisine": "Sandwiches and Salads" }} ) # end-bulk-update-many # start-bulk-replace-one -operation = pymongo.ReplaceOne( - { "restaurant_id": "1234" }, - { +operation = ReplaceOne( + namespace="sample_restaurants.restaurants", + filter={ "restaurant_id": "1234" }, + replacement={ "name": "Mongo's Pizza", "cuisine": "Pizza", "borough": "Brooklyn", @@ -36,45 +40,82 @@ # end-bulk-replace-one # start-bulk-delete-one -operation = pymongo.DeleteOne({ "restaurant_id": "5678" }) +operation = DeleteOne( + namespace="sample_restaurants.restaurants", + filter={ "restaurant_id": "5678" } +) # end-bulk-delete-one # start-bulk-delete-many -operation = pymongo.DeleteMany({ "name": "Mongo's Deli" }) +operation = DeleteMany( + namespace="sample_restaurants.restaurants", + filter={ "name": "Mongo's Deli" } +) # end-bulk-delete-many -# start-bulk-write-mixed +# start-bulk-write-mixed-collection operations = [ - pymongo.InsertOne( - { + InsertOne( + document={ "name": "Mongo's Deli", "cuisine": "Sandwiches", "borough": "Manhattan", "restaurant_id": "1234" } ), - pymongo.InsertOne( - { + InsertOne( + document={ "name": "Mongo's Deli", "cuisine": "Sandwiches", "borough": "Brooklyn", "restaurant_id": "5678" } ), - pymongo.UpdateMany( - { "name": "Mongo's Deli" }, - { "$set": { "cuisine": "Sandwiches and Salads" }}, + UpdateMany( + filter={ "name": "Mongo's Deli" }, + update={ "$set": { "cuisine": "Sandwiches and Salads" }} ), - pymongo.DeleteOne( - { "restaurant_id": "1234" } + DeleteOne( + filter={ "restaurant_id": "1234" } ) ] results = restaurants.bulk_write(operations) print(results) -# end-bulk-write-mixed +# end-bulk-write-mixed-collection + + +# start-bulk-write-mixed-client +operations = [ + InsertOne( + namespace="sample_mflix.movies", + document={ + "title": "Minari", + "runtime": 217, + "genres": ["Drama", "Comedy"] + } + ), + UpdateOne( + namespace="sample_mflix.movies", + filter={ "title": "Minari" }, + update={ "$set": { "runtime": 117 }} + ), + DeleteMany( + namespace="sample_restaurants.restaurants", + filter={ "cuisine": "French" } + ) +] + +results = client.bulk_write(operations) + +print(results) +# end-bulk-write-mixed-client # start-bulk-write-unordered results = restaurants.bulk_write(operations, ordered=False) -# end-bulk-write-unordered \ No newline at end of file +# end-bulk-write-unordered + +# start-bulk-write-verbose +results = client.bulk_write(operations, verbose_results=True) +# end-bulk-write-verbose \ No newline at end of file diff --git a/source/write/bulk-write.txt b/source/write/bulk-write.txt index 3a8d5b81..a9e73d52 100644 --- a/source/write/bulk-write.txt +++ b/source/write/bulk-write.txt @@ -20,19 +20,34 @@ Bulk Write Operations Overview -------- -Consider a scenario in which you want to insert a document into a collection, -update multiple other documents, then delete a document. If you use -individual methods, each operation requires its own database call. This guide -shows you how to use bulk write operations to perform multiple write operations -in a single database call. +In this guide, you can learn how to use {+driver-short+} to +perform **bulk operations**. Bulk operations reduce the number +of calls to the server by performing multiple write operations +in a single method. + +The ``Collection`` and ``MongoClient`` classes both provide a ``bulk_write()`` +method. When calling ``bulk_write()`` on a ``Collection`` instance, you can +perform multiple write operations on a single collection. When calling +``bulk_write()`` on a ``MongoClient`` instance, you can perform bulk writes across +multiple namespaces. In MongoDB, a namespace consists of the database name and the collection +name in the format ``.``. + +.. important:: + + To perform bulk operations on a ``MongoClient`` instance, + ensure that your application meets the following + requirements: + + - Uses {+driver-short+} v4.9 or later + - Connects to {+mdb-server+} v8.0 or later Sample Data ~~~~~~~~~~~ -The examples in this guide use the ``sample_restaurants.restaurants`` collection -from the :atlas:`Atlas sample datasets `. To learn how to create a -free MongoDB Atlas cluster and load the sample datasets, see the -:ref:`` tutorial. +The examples in this guide use the ``sample_restaurants.restaurants`` +and ``sample_mflix.movies`` collections from the :atlas:`Atlas sample datasets +`. To learn how to create a free MongoDB Atlas cluster +and load the sample datasets, see the :ref:`` tutorial. Define the Write Operations --------------------------- @@ -49,13 +64,28 @@ the following operation classes: Then, pass a list of these instances to the ``bulk_write()`` method. -The following sections show how to create and use instances of the preceding classes. +.. important:: + + Ensure that you import the write operation classes into your application + file, as shown in the following code: + + .. code-block:: python + + from pymongo import InsertOne, UpdateOne, UpdateMany, ReplaceOne, DeleteOne, DeleteMany + +The following sections show how to create instances of the preceding classes, +which you can use to perform collection and client bulk operations. Insert Operations ~~~~~~~~~~~~~~~~~ To perform an insert operation, create an instance of ``InsertOne`` and specify -the document you want to insert. +the document you want to insert. Pass the following keyword arguments to the +``InsertOne`` constructor: + +- ``namespace``: The namespace in which to insert the document. This argument + is optional if you perform the bulk operation on a single collection. +- ``document``: The document to insert. The following example creates an instance of ``InsertOne``: @@ -79,8 +109,11 @@ Update Operations To update a document, create an instance of ``UpdateOne`` and pass in the following arguments: -- A **query filter** that specifies the criteria used to match documents in your collection -- The update operation you want to perform. For more information about update +- ``namespace``: The namespace in which to perform the update. This argument is optional if + you perform the bulk operation on a single collection. +- ``filter``: The **query filter** that specifies the criteria used to match documents in + your collection. +- ``update``: The update you want to perform. For more information about update operations, see the :manual:`Field Update Operators ` guide in the {+mdb-server+} manual. @@ -111,8 +144,14 @@ Replace Operations A replace operation removes all fields and values of a specified document and replaces them with new ones. To perform a replace operation, create an instance -of ``ReplaceOne`` and pass it a query filter and the fields and values you want -to store in the matching document. +of ``ReplaceOne`` and pass in the following arguments: + +- ``namespace``: The namespace in which to perform the replace operation. This + argument is optional if you perform the bulk operation on a single collection. +- ``filter``: The **query filter** that specifies the criteria used to match the + document to replace. +- ``replacement``: The document that includes the new fields and values you want + to store in the matching document. The following example creates an instance of ``ReplaceOne``: @@ -127,9 +166,15 @@ To replace multiple documents, you must create an instance of ``ReplaceOne`` for Delete Operations ~~~~~~~~~~~~~~~~~ -To delete a document, create an instance of ``DeleteOne`` and pass in a -query filter specifying the document you want to delete. ``DeleteOne`` removes -only *the first* document that matches your query filter. +To delete a document, create an instance of ``DeleteOne`` and pass in +the following arguments: + +- ``namespace``: The namespace in which to delete the document. This argument is + optional if you perform the bulk operation on a single collection. +- ``filter``: The **query filter** that specifies the criteria used to match the + document to delete. + +``DeleteOne`` removes only *the first* document that matches your query filter. The following example creates an instance of ``DeleteOne``: @@ -140,7 +185,7 @@ The following example creates an instance of ``DeleteOne``: :copyable: To delete multiple documents, create an instance of ``DeleteMany`` and pass in a -query filter specifying the document you want to delete. ``DeleteMany`` removes +namespace and query filter specifying the document you want to delete. ``DeleteMany`` removes *all* documents that match your query filter. The following example creates an instance of ``DeleteMany``: @@ -151,46 +196,99 @@ The following example creates an instance of ``DeleteMany``: :language: python :copyable: -Call the ``bulk_write()`` Method --------------------------------- +.. _pymongo-bulk-write-call: + +Call the bulk_write() Method +---------------------------- After you define a class instance for each operation you want to perform, -pass a list of these instances to the ``bulk_write()`` method. -By default, the method runs the operations in the order -they're defined in the list. +pass a list of these instances to the ``bulk_write()`` method. Call the +``bulk_write()`` method on a ``Collection`` instance to write to a single +collection or a ``MongoClient`` instance to write to multiple namespaces. + +If any of the write operations called on a ``Collection`` fail, {+driver-short+} raises a +``BulkWriteError`` and does not perform any further operations. +``BulkWriteError`` provides a ``details`` attribute that includes the operation +that failed, and details about the exception. + +If any of the write operations called on a ``MongoClient`` fail, {+driver-short+} raises a +``ClientBulkWriteException`` and does not perform any further operations. +``ClientBulkWriteException`` provides an ``error`` attribute that includes +information about the exception. + +.. note:: + + When {+driver-short+} runs a bulk operation, it uses the ``write_concern`` of the + collection or client on which the operation is running. You can also set + a write concern for the operation when using the ``MongoClient.bulk_write()`` + method. The driver reports all write concern errors after attempting all operations, + regardless of execution order. + + To learn more about write concerns, see :manual:`Write Concern ` + in the {+mdb-server+} manual. + +.. _pymongo-bulk-write-collection-ex: + +Collection Bulk Write Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The following example performs multiple write operations by using the -``bulk_write()`` method: +The following example performs multiple write operations on the +``restaurants`` collection by using the ``bulk_write()`` method +on a ``Collection`` instance: .. io-code-block:: + :copyable: .. input:: /includes/write/bulk-write.py - :start-after: start-bulk-write-mixed - :end-before: end-bulk-write-mixed + :start-after: start-bulk-write-mixed-collection + :end-before: end-bulk-write-mixed-collection :language: python .. output:: + :visible: false - BulkWriteResult({'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 2, 'nUpserted': 0, 'nMatched': 2, 'nModified': 2, 'nRemoved': 1, 'upserted': []}, acknowledged=True) + BulkWriteResult({'writeErrors': [], 'writeConcernErrors': [], 'nInserted': 2, + 'nUpserted': 0, 'nMatched': 2, 'nModified': 2, 'nRemoved': 1, 'upserted': []}, + acknowledged=True) -If any of the write operations fail, {+driver-short+} raises a -``BulkWriteError`` and does not perform any further operations. -``BulkWriteError`` provides a ``details`` attribute that includes the operation -that failed, and details about the exception. +.. _pymongo-bulk-write-client-ex: -.. note:: +Client Bulk Write Example +~~~~~~~~~~~~~~~~~~~~~~~~~ - When {+driver-short+} runs a bulk operation, it uses the ``write_concern`` of the - collection in which the operation is running. The driver reports all write - concern errors after attempting all operations, regardless of execution order. +The following example performs multiple write operations on the +``sample_restaurants.restaurants`` and ``sample_mflix.movies`` +namespaces by using the ``bulk_write()`` method on a ``MongoClient`` +instance: + +.. io-code-block:: + :copyable: + + .. input:: /includes/write/bulk-write.py + :start-after: start-bulk-write-mixed-client + :end-before: end-bulk-write-mixed-client + :language: python + + .. output:: + :visible: false + + ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [], + 'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1, + 'nModified': 1, 'nDeleted': 344, 'insertResults': {}, 'updateResults': {}, + 'deleteResults': {}}, acknowledged=True, verbose=False) Customize Bulk Write Operations ------------------------------- The ``bulk_write()`` method optionally accepts additional parameters, which represent options you can use to configure the bulk write -operation. If you don't specify any additional options, the driver does not customize -the bulk write operation. +operation. + +Collection Bulk Write Options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following table describes the options you can pass +to the ``Collection.bulk_write()`` method: .. list-table:: :widths: 30 70 @@ -231,7 +329,8 @@ the bulk write operation. ` in the {+mdb-server+} manual. -The following example calls the ``bulk_write()`` method from the preceding example, with the ``ordered`` option set +The following example calls the ``bulk_write()`` method from the preceding +:ref:`pymongo-bulk-write-collection-ex` but sets the ``ordered`` option to ``False``: .. literalinclude:: /includes/write/bulk-write.py @@ -248,10 +347,98 @@ reports the errors only after attempting all operations. Unordered bulk operations do not guarantee order of execution. The order can differ from the way you list them to optimize the runtime. -Return Value ------------- +Client Bulk Write Options +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following table describes the options you can pass +to the ``MongoClient.bulk_write()`` method: + +.. list-table:: + :widths: 30 70 + :header-rows: 1 + + * - Property + - Description + + * - ``session`` + - | An instance of ``ClientSession``. For more information, see the `API + documentation <{+api-root+}pymongo/client_session.html#pymongo.client_session.ClientSession>`__. + + * - ``ordered`` + - | If ``True``, the driver performs the write operations in the order + provided. If an error occurs, the remaining operations are not + attempted. + | + | If ``False``, the driver performs the operations in an + arbitrary order and attempts to perform all operations. + | Defaults to ``True``. + + * - ``verbose_results`` + - | Specifies whether the operation returns detailed results for each + successful operation. + | Defaults to ``False``. + + * - ``bypass_document_validation`` + - | Specifies whether the operation bypasses document-level validation. For more + information, see :manual:`Schema + Validation ` in the MongoDB + Server manual. + | Defaults to ``False``. + + * - ``comment`` + - | A comment to attach to the operation. For more information, see the :manual:`delete command + fields ` guide in the + {+mdb-server+} manual. + + * - ``let`` + - | A map of parameter names and values. Values must be constant or closed + expressions that don't reference document fields. For more information, + see the :manual:`let statement + ` in the + {+mdb-server+} manual. + + * - ``write_concern`` + - | Specifies the write concern to use for the bulk operation. + For more information, see :manual:`Write Concern ` + in the {+mdb-server+} manual. + +The following example calls the ``bulk_write()`` method from the preceding +:ref:`pymongo-bulk-write-client-ex` but sets the ``verbose_results`` option +to ``True``: + +.. io-code-block:: + :copyable: -The ``bulk_write()`` method returns a ``BulkWriteResult`` object. The + .. input:: /includes/write/bulk-write.py + :start-after: start-bulk-write-verbose + :end-before: end-bulk-write-verbose + :language: python + + .. output:: + :visible: false + + ClientBulkWriteResult({'anySuccessful': True, 'error': None, 'writeErrors': [], + 'writeConcernErrors': [], 'nInserted': 1, 'nUpserted': 0, 'nMatched': 1, 'nModified': 1, + 'nDeleted': 344, 'insertResults': {0: InsertOneResult(ObjectId('...'), + acknowledged=True)}, 'updateResults': {1: UpdateResult({'ok': 1.0, 'idx': 1, 'n': 1, + 'nModified': 1}, acknowledged=True)}, 'deleteResults': {2: DeleteResult({'ok': 1.0, + 'idx': 2, 'n': 344}, acknowledged=True)}}, acknowledged=True, verbose=True) + +Return Values +------------- + +This section describes the return value of the following +bulk operation methods: + +- :ref:`Collection.bulk_write() ` +- :ref:`MongoClient.bulk_write() ` + +.. _pymongo-bulk-write-collection-return: + +Collection Bulk Write Return Value +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``Collection.bulk_write()`` method returns a ``BulkWriteResult`` object. The ``BulkWriteResult`` object contains the following properties: .. list-table:: @@ -286,6 +473,54 @@ The ``bulk_write()`` method returns a ``BulkWriteResult`` object. The - | A map of the operation's index to the ``_id`` of the upserted documents, if applicable. +.. _pymongo-bulk-write-client-return: + +Client Bulk Write Return Value +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``MongoClient.bulk_write()`` method returns a ``ClientBulkWriteResult`` object. The +``ClientBulkWriteResult`` object contains the following properties: + +.. list-table:: + :widths: 30 70 + :header-rows: 1 + + * - Property + - Description + + * - ``acknowledged`` + - | Indicates if the server acknowledged the write operation. + + * - ``bulk_api_result`` + - | The raw bulk API result returned by the server. + + * - ``delete_results`` + - | A map of any successful delete operations and their results. + + * - ``deleted_count`` + - | The number of documents deleted, if any. + + * - ``has_verbose_results`` + - | Indicates whether the returned results are verbose. + + * - ``insert_results`` + - | A map of any successful insert operations and their results. + + * - ``inserted_count`` + - | The number of documents inserted, if any. + + * - ``matched_count`` + - | The number of documents matched for an update, if applicable. + + * - ``modified_count`` + - | The number of documents modified, if any. + + * - ``update_results`` + - | A map of any successful update operations and their results. + + * - ``upserted_count`` + - | The number of documents upserted, if any. + Additional Information ---------------------- @@ -302,7 +537,8 @@ API Documentation To learn more about any of the methods or types discussed in this guide, see the following API Documentation: -- `bulk_write() <{+api-root+}pymongo/collection.html#pymongo.collection.Collection.bulk_write>`__ +- `Collection.bulk_write() <{+api-root+}pymongo/collection.html#pymongo.collection.Collection.bulk_write>`__ +- `MongoClient.bulk_write() <{+api-root+}pymongo/mongo_client.html#pymongo.mongo_client.MongoClient.bulk_write>`__ - `InsertOne <{+api-root+}pymongo/operations.html#pymongo.operations.InsertOne>`__ - `UpdateOne <{+api-root+}pymongo/operations.html#pymongo.operations.UpdateOne>`__ - `UpdateMany <{+api-root+}pymongo/operations.html#pymongo.operations.UpdateMany>`__ @@ -310,4 +546,6 @@ guide, see the following API Documentation: - `DeleteOne <{+api-root+}pymongo/operations.html#pymongo.operations.DeleteOne>`__ - `DeleteMany <{+api-root+}pymongo/operations.html#pymongo.operations.DeleteMany>`__ - `BulkWriteResult <{+api-root+}pymongo/results.html#pymongo.results.BulkWriteResult>`__ +- `ClientBulkWriteResult <{+api-root+}pymongo/results.html#pymongo.results.ClientBulkWriteResult>`__ - `BulkWriteError <{+api-root+}pymongo/errors.html#pymongo.errors.BulkWriteError>`__ +- `ClientBulkWriteException <{+api-root+}pymongo/errors.html#pymongo.errors.ClientBulkWriteException>`__ diff --git a/source/write/transactions.txt b/source/write/transactions.txt index 229af576..aa37febd 100644 --- a/source/write/transactions.txt +++ b/source/write/transactions.txt @@ -140,6 +140,10 @@ methods described in the preceding section to manually manage the transaction li {+driver-short+} does not support running parallel operations within a single transaction. + If you're using {+mdb-server+} v8.0 or later, you can perform write operations on multiple + namespaces within a single transaction by calling the ``bulk_write()`` method on a ``MongoClient`` + instance. For more information, see the :ref:`pymongo-bulk-write` guide. + Additional Information ----------------------