diff --git a/source/index.txt b/source/index.txt index e375ec73..e9f192d1 100644 --- a/source/index.txt +++ b/source/index.txt @@ -24,6 +24,7 @@ MongoDB {+driver-short+} Documentation Data Formats Logging Monitoring + Serialization Third-Party Tools FAQ Troubleshooting @@ -100,6 +101,22 @@ Specialized Data Formats Learn how to work with specialized data formats and custom types in the :ref:`pymongo-data-formats` section. +Logging +------- + +Learn how to configure logging in the :ref:`pymongo-logging` section. + +Monitoring +---------- + +Learn how to monitor changes to your application in the :ref:`pymongo-monitoring` section. + +Serialization +------------- + +Learn how {+driver-short+} serializes and deserializes data in the +:ref:`pymongo-serialization` section. + Third-Party Tools ----------------- diff --git a/source/serialization.txt b/source/serialization.txt new file mode 100644 index 00000000..99c5c432 --- /dev/null +++ b/source/serialization.txt @@ -0,0 +1,92 @@ +.. _pymongo-serialization: + +============= +Serialization +============= + +.. facet:: + :name: genre + :values: reference + +.. meta:: + :keywords: class, map, deserialize + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +Overview +-------- + +In this guide, you can learn how to use {+driver-short+} to perform +serialization. + +Serialization is the process of mapping a {+language+} object to a BSON +document for storage in MongoDB. {+driver-short+} automatically converts basic {+language+} +types into BSON when you insert a document into a collection. Similarly, when you retrieve a +document from a collection, {+driver-short+} automatically converts the returned BSON +back into the corresponding {+language+} types. + +You can use {+driver-short+} to serialize and deserialize the following {+language+} +types: + +- ``str`` +- ``int`` +- ``float`` +- ``bool`` +- ``datetime.datetime`` +- ``list`` +- ``dict`` +- ``None`` + +For a complete list of {+language+}-to-BSON mappings, see the `bson <{+api-root+}bson/index.html>`__ +API documentation. + +Custom Classes +-------------- + +To serialize and deserialize custom {+language+} classes, you must implement custom logic +to handle the conversion. The following sections show how to serialize and deserialize +custom classes. + +Serializing Custom Classes +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To serialize a custom class, you must convert the class to a dictionary. The following +example serializes a custom class by using the ``vars()`` method, and then inserts the +serialized object into a collection: + +.. code-block:: python + + class Restaurant: + def __init__(self, name, cuisine): + self.name = name + self.cuisine = cuisine + + restaurant = Guitar("Example Cafe", "Coffee") + restaurant_dict = vars(restaurant) + + collection.insert_one(restaurant_dict) + +To learn more about inserting documents into a collection, see the :ref:`pymongo-write-insert` +guide. + +Deserializing Custom Classes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To deserialize a custom class, you must convert the dictionary back into an instance of +the class. The following example retrieves a document from a collection, and then converts +it back into a ``Restaurant`` object from the preceding example: + +.. code-block:: python + + def deserialize_restaurant(doc): + return Restaurant(name=doc["name"], cuisine=doc["cuisine"]) + + restaurant_doc = collection.find_one({"name": "Example Cafe"}) + restaurant = deserialize_restaurant(restaurant_doc) + +To learn more about retrieving documents from a collection, see the :ref:`pymongo-retrieve` +guide. diff --git a/source/troubleshooting.txt b/source/troubleshooting.txt index 495e2708..c20b02c6 100644 --- a/source/troubleshooting.txt +++ b/source/troubleshooting.txt @@ -110,149 +110,6 @@ frameworks. if __name__ == "__main__": app.run() -Query Works in the Shell But Not in {+driver-short+} -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -After the ``_id`` field, which is always first, the key-value pairs in a BSON document can -be in any order. The ``mongo`` shell preserves key order when reading and writing -data, as shown by the fields "b" and "a" in the following code example: - -.. code-block:: javascript - - // mongo shell - db.collection.insertOne( { "_id" : 1, "subdocument" : { "b" : 1, "a" : 1 } } ) - // Returns: WriteResult({ "nInserted" : 1 }) - - db.collection.findOne() - // Returns: { "_id" : 1, "subdocument" : { "b" : 1, "a" : 1 } } - -{+driver-short+} represents BSON documents as Python dictionaries by default, -and the order of keys in dictionaries is not defined. In Python, a dictionary declared with -the "a" key first is the same as one with the "b" key first. In the following example, -the keys are displayed in the same order regardless of their order in the ``print`` -statement: - -.. code-block:: python - - print({'a': 1.0, 'b': 1.0}) - # Returns: {'a': 1.0, 'b': 1.0} - - print({'b': 1.0, 'a': 1.0}) - # Returns: {'a': 1.0, 'b': 1.0} - -Similarly, Python dictionaries might not show keys in the order they are -stored in BSON. The following example shows the result of printing the document -inserted in a preceding example: - -.. code-block:: python - - print(collection.find_one()) - # Returns: {'_id': 1.0, 'subdocument': {'a': 1.0, 'b': 1.0}} - -To preserve the order of keys when reading BSON, use the ``SON`` class, -which is a dictionary that remembers its key order. - -The following code example shows how to create a collection -configured to use the ``SON`` class: - -.. code-block:: python - - from bson import CodecOptions, SON - - opts = CodecOptions(document_class=SON) - - CodecOptions(document_class=...SON..., tz_aware=False, uuid_representation=UuidRepresentation.UNSPECIFIED, unicode_decode_error_handler='strict', tzinfo=None, type_registry=TypeRegistry(type_codecs=[], fallback_encoder=None), datetime_conversion=DatetimeConversion.DATETIME) - collection_son = collection.with_options(codec_options=opts) - -When you find the preceding subdocument, the driver represents query results with -``SON`` objects and preserves key order: - -.. io-code-block:: - - .. input:: - :language: python - - print(collection_son.find_one()) - - .. output:: - - SON([('_id', 1.0), ('subdocument', SON([('b', 1.0), ('a', 1.0)]))]) - -The subdocument's actual storage layout is now visible: "b" is before "a". - -Because a Python dictionary's key order is not defined, you cannot predict how it will be -serialized to BSON. However, MongoDB considers subdocuments equal only if their -keys have the same order. If you use a Python dictionary to query on a subdocument, it may -not match: - -.. io-code-block:: - - .. input:: - :language: python - - collection.find_one({'subdocument': {'b': 1.0, 'a': 1.0}}) is None - - .. output:: - - True - -Because Python considers the two dictionaries the same, swapping the key order in your query -makes no difference: - -.. io-code-block:: - - .. input:: - :language: python - - collection.find_one({'subdocument': {'b': 1.0, 'a': 1.0}}) is None - - .. output:: - - True - -You can solve this in two ways. First, you can match the subdocument field-by-field: - -.. io-code-block:: - - .. input:: - :language: python - - collection.find_one({'subdocument.a': 1.0, - 'subdocument.b': 1.0}) - - .. output:: - - {'_id': 1.0, 'subdocument': {'a': 1.0, 'b': 1.0}} - -The query matches any subdocument with an "a" of 1.0 and a "b" of 1.0, -regardless of the order in which you specify them in Python, or the order in which they're -stored in BSON. This query also now matches subdocuments with additional -keys besides "a" and "b", whereas the previous query required an exact match. - -The second solution is to use a ``~bson.son.SON`` object to specify the key order: - -.. io-code-block:: - - .. input:: - :language: python - - query = {'subdocument': SON([('b', 1.0), ('a', 1.0)])} - collection.find_one(query) - - .. output:: - - {'_id': 1.0, 'subdocument': {'a': 1.0, 'b': 1.0}} - -The driver preserves the key order you use when you create a ``~bson.son.SON`` -when serializing it to BSON and using it as a query. Thus, you can create a -subdocument that exactly matches the subdocument in the collection. - -.. note:: - - For more information about subdocument matching, see the - `Query on Embedded/Nested Documents `__ - guide in the {+mdb-server+} documentation. - Cursors -------