diff --git a/source/data-formats/bson.txt b/source/data-formats/bson.txt index 3a91f882..82488036 100644 --- a/source/data-formats/bson.txt +++ b/source/data-formats/bson.txt @@ -107,10 +107,10 @@ The following example reads the sample BSON document from ``file.bson``: .. input:: :language: python - with open("file.bson", "rb") as file: - data = file.read() - document = bson.decode(data) - print(document) + with open("file.bson", "rb") as file: + data = file.read() + document = bson.decode(data) + print(document) .. output:: :visible: false @@ -138,25 +138,53 @@ constructor to ``RawBSONDocument``. first convert it to a {+language+} dictionary. The following example configures a ``MongoClient`` object to use ``RawBSONDocument`` objects -to model the collection, then retrieves the sample document from the preceding examples: +to model the collection, then retrieves the sample document from the preceding examples. +Select the :guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding +code. -.. io-code-block:: - :copyable: true +.. tabs:: + + .. tab:: Synchronous + :tabid: sync - .. input:: - :language: python - - from bson.raw_bson import RawBSONDocument + .. io-code-block:: + :copyable: true - client = pymongo.MongoClient("", document_class=RawBSONDocument) - collection = client.sample_restaurants.restaurants - raw_doc = collection.find_one({"name": "Mongo's Pizza"}) - print(type(raw_doc)) + .. input:: + :language: python + + from bson.raw_bson import RawBSONDocument - .. output:: - :visible: false + client = pymongo.MongoClient("", document_class=RawBSONDocument) + collection = client.sample_restaurants.restaurants + raw_doc = collection.find_one({"name": "Mongo's Pizza"}) + print(type(raw_doc)) + + .. output:: + :visible: false + + + + .. tab:: Asynchronous + :tabid: async + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + from bson.raw_bson import RawBSONDocument + + client = pymongo.AsyncMongoClient("", document_class=RawBSONDocument) + collection = client.sample_restaurants.restaurants + raw_doc = await collection.find_one({"name": "Mongo's Pizza"}) + print(type(raw_doc)) + + .. output:: + :visible: false - + API Documentation ----------------- diff --git a/source/data-formats/custom-types.txt b/source/data-formats/custom-types.txt index 9caf3da9..1f33b152 100644 --- a/source/data-formats/custom-types.txt +++ b/source/data-formats/custom-types.txt @@ -29,26 +29,54 @@ the driver doesn't understand. For example, the BSON library's ``Decimal128`` type is distinct from Python's built-in ``Decimal`` type. Attempting to save an instance of ``Decimal`` with {+driver-short+} results in an -``InvalidDocument`` exception, as shown in the following code example: +``InvalidDocument`` exception, as shown in the following code example. Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: -.. io-code-block:: - :copyable: true +.. tabs:: - .. input:: - :language: python + .. tab:: Synchronous + :tabid: sync - from decimal import Decimal + .. io-code-block:: + :copyable: true - num = Decimal("45.321") - db["coll"].insert_one({"num": num}) + .. input:: + :language: python - .. output:: - :language: shell + from decimal import Decimal - Traceback (most recent call last): - ... - bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), of - type: + num = Decimal("45.321") + db["coll"].insert_one({"num": num}) + + .. output:: + :language: shell + + Traceback (most recent call last): + ... + bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), of + type: + + .. tab:: Asynchronous + :tabid: async + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + from decimal import Decimal + + num = Decimal("45.321") + await db["coll"].insert_one({"num": num}) + + .. output:: + :language: shell + + Traceback (most recent call last): + ... + bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), of + type: The following sections show how to define a custom type for this ``Decimal`` type. @@ -154,46 +182,97 @@ object as a keyword argument. Pass your ``CodecOptions`` object to the codec_options = CodecOptions(type_registry=type_registry) collection = db.get_collection("test", codec_options=codec_options) -You can then encode and decode instances of the ``Decimal`` class: +You can then encode and decode instances of the ``Decimal`` class. Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: -.. io-code-block:: - :copyable: true +.. tabs:: + + .. tab:: Synchronous + :tabid: sync - .. input:: - :language: python + .. io-code-block:: + :copyable: true - import pprint - - collection.insert_one({"num": Decimal("45.321")}) - my_doc = collection.find_one() - pprint.pprint(my_doc) + .. input:: + :language: python - .. output:: - :language: shell - - {'_id': ObjectId('...'), 'num': Decimal('45.321')} + import pprint + + collection.insert_one({"num": Decimal("45.321")}) + my_doc = collection.find_one() + pprint.pprint(my_doc) + + .. output:: + :language: shell + + {'_id': ObjectId('...'), 'num': Decimal('45.321')} + + .. tab:: Asynchronous + :tabid: async + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + import pprint + + await collection.insert_one({"num": Decimal("45.321")}) + my_doc = await collection.find_one() + pprint.pprint(my_doc) + + .. output:: + :language: shell + + {'_id': ObjectId('...'), 'num': Decimal('45.321')} To see how MongoDB stores an instance of the custom type, create a new collection object without the customized codec options, then use it to retrieve the document containing the custom type. The following example shows that {+driver-short+} stores an instance of the ``Decimal`` class as a ``Decimal128`` -value: +value. Select the :guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the +corresponding code: + +.. tabs:: + + .. tab:: Synchronous + :tabid: sync + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + import pprint + + new_collection = db.get_collection("test") + pprint.pprint(new_collection.find_one()) -.. io-code-block:: - :copyable: true + .. output:: + :language: shell - .. input:: - :language: python + {'_id': ObjectId('...'), 'num': Decimal128('45.321')} - import pprint + .. tab:: Asynchronous + :tabid: async - new_collection = db.get_collection("test") - pprint.pprint(new_collection.find_one()) + .. io-code-block:: + :copyable: true - .. output:: - :language: shell + .. input:: + :language: python - {'_id': ObjectId('...'), 'num': Decimal128('45.321')} + import pprint + + new_collection = db.get_collection("test") + pprint.pprint(await new_collection.find_one()) + + .. output:: + :language: shell + + {'_id': ObjectId('...'), 'num': Decimal128('45.321')} Encode a Subtype ---------------- @@ -209,23 +288,48 @@ return its value as an integer: return int(self) If you try to save an instance of the ``DecimalInt`` class without first registering a type -codec for it, {+driver-short+} raises an error: +codec for it, {+driver-short+} raises an error. Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: + +.. tabs:: + + .. tab:: Synchronous + :tabid: sync + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + collection.insert_one({"num": DecimalInt("45.321")}) -.. io-code-block:: - :copyable: true + .. output:: + :language: shell - .. input:: - :language: python + Traceback (most recent call last): + ... + bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), + of type: - collection.insert_one({"num": DecimalInt("45.321")}) + .. tab:: Asynchronous + :tabid: async - .. output:: - :language: shell + .. io-code-block:: + :copyable: true - Traceback (most recent call last): - ... - bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), - of type: + .. input:: + :language: python + + await collection.insert_one({"num": DecimalInt("45.321")}) + + .. output:: + :language: shell + + Traceback (most recent call last): + ... + bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), + of type: To encode an instance of the ``DecimalInt`` class, you must define a type codec for the class. This type codec must inherit from the parent class's codec, ``DecimalCodec``, @@ -240,31 +344,64 @@ as shown in the following example: return DecimalInt You can then add the sublcass's type codec to the type registry and encode instances -of the custom type: +of the custom type. Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: -.. io-code-block:: - :copyable: true +.. tabs:: - .. input:: - :language: python + .. tab:: Synchronous + :tabid: sync - import pprint - from bson.codec_options import CodecOptions + .. io-code-block:: + :copyable: true - decimal_int_codec = DecimalIntCodec() - type_registry = TypeRegistry([decimal_codec, decimal_int_codec]) - codec_options = CodecOptions(type_registry=type_registry) + .. input:: + :language: python - collection = db.get_collection("test", codec_options=codec_options) - collection.insert_one({"num": DecimalInt("45.321")}) - - my_doc = collection.find_one() - pprint.pprint(my_doc) + import pprint + from bson.codec_options import CodecOptions + + decimal_int_codec = DecimalIntCodec() + type_registry = TypeRegistry([decimal_codec, decimal_int_codec]) + codec_options = CodecOptions(type_registry=type_registry) + + collection = db.get_collection("test", codec_options=codec_options) + collection.insert_one({"num": DecimalInt("45.321")}) + + my_doc = collection.find_one() + pprint.pprint(my_doc) + + .. output:: + :language: shell + + {'_id': ObjectId('...'), 'num': Decimal('45.321')} - .. output:: - :language: shell + .. tab:: Asynchronous + :tabid: async - {'_id': ObjectId('...'), 'num': Decimal('45.321')} + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + import pprint + from bson.codec_options import CodecOptions + + decimal_int_codec = DecimalIntCodec() + type_registry = TypeRegistry([decimal_codec, decimal_int_codec]) + codec_options = CodecOptions(type_registry=type_registry) + + collection = db.get_collection("test", codec_options=codec_options) + await collection.insert_one({"num": DecimalInt("45.321")}) + + my_doc = await collection.find_one() + pprint.pprint(my_doc) + + .. output:: + :language: shell + + {'_id': ObjectId('...'), 'num': Decimal('45.321')} .. note:: @@ -306,24 +443,50 @@ The following code example shows this process: collection = db.get_collection("test", codec_options=codec_options) You can then use this reference to a collection to store instances of the ``Decimal`` -class: +class. Select the :guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the +corresponding code: + +.. tabs:: + + .. tab:: Synchronous + :tabid: sync -.. io-code-block:: - :copyable: true + .. io-code-block:: + :copyable: true - .. input:: - :language: python + .. input:: + :language: python - import pprint + import pprint - collection.insert_one({"num": Decimal("45.321")}) - my_doc = collection.find_one() - pprint.pprint(my_doc) + collection.insert_one({"num": Decimal("45.321")}) + my_doc = collection.find_one() + pprint.pprint(my_doc) - .. output:: - :language: shell + .. output:: + :language: shell - {'_id': ObjectId('...'), 'num': Decimal128('45.321')} + {'_id': ObjectId('...'), 'num': Decimal128('45.321')} + + .. tab:: Asynchronous + :tabid: async + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + import pprint + + await collection.insert_one({"num": Decimal("45.321")}) + my_doc = await collection.find_one() + pprint.pprint(my_doc) + + .. output:: + :language: shell + + {'_id': ObjectId('...'), 'num': Decimal128('45.321')} .. note:: @@ -383,36 +546,74 @@ back into Python objects: return value You can then add the ``PickledBinaryDecoder`` to the codec options for a collection -and use it to encode and decode your custom types: +and use it to encode and decode your custom types. Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: + +.. tabs:: + + .. tab:: Synchronous + :tabid: sync + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + from bson.codec_options import CodecOptions,TypeRegistry + + codec_options = CodecOptions( + type_registry=TypeRegistry( + [PickledBinaryDecoder()], fallback_encoder=fallback_pickle_encoder + ) + ) + + collection = db.get_collection("test", codec_options=codec_options) + collection.insert_one( + {"_id": 1, "str": MyStringType("hello world"), "num": MyNumberType(2)} + ) + my_doc = collection.find_one() + + print(isinstance(my_doc["str"], MyStringType)) + print(isinstance(my_doc["num"], MyNumberType)) + + .. output:: + :language: shell + + True + True + + .. tab:: Asynchronous + :tabid: async -.. io-code-block:: - :copyable: true + .. io-code-block:: + :copyable: true - .. input:: - :language: python + .. input:: + :language: python - from bson.codec_options import CodecOptions,TypeRegistry + from bson.codec_options import CodecOptions,TypeRegistry - codec_options = CodecOptions( - type_registry=TypeRegistry( - [PickledBinaryDecoder()], fallback_encoder=fallback_pickle_encoder - ) - ) + codec_options = CodecOptions( + type_registry=TypeRegistry( + [PickledBinaryDecoder()], fallback_encoder=fallback_pickle_encoder + ) + ) - collection = db.get_collection("test", codec_options=codec_options) - collection.insert_one( - {"_id": 1, "str": MyStringType("hello world"), "num": MyNumberType(2)} - ) - my_doc = collection.find_one() + collection = db.get_collection("test", codec_options=codec_options) + await collection.insert_one( + {"_id": 1, "str": MyStringType("hello world"), "num": MyNumberType(2)} + ) + my_doc = await collection.find_one() - print(isinstance(my_doc["str"], MyStringType)) - print(isinstance(my_doc["num"], MyNumberType)) + print(isinstance(my_doc["str"], MyStringType)) + print(isinstance(my_doc["num"], MyNumberType)) - .. output:: - :language: shell + .. output:: + :language: shell - True - True + True + True Limitations ----------- diff --git a/source/data-formats/dates-and-times.txt b/source/data-formats/dates-and-times.txt index 01d18700..d3f146be 100644 --- a/source/data-formats/dates-and-times.txt +++ b/source/data-formats/dates-and-times.txt @@ -124,27 +124,56 @@ Naive UTC datetime By default, {+driver-short+} retrieves UTC ``datetime`` values with no supplemental information. The following code example retrieves the sample document and prints the ``datetime`` value. The printed value is identical to -the one in the sample document. +the one in the sample document. Select the :guilabel:`Synchronous` or +:guilabel:`Asynchronous` tab to see the corresponding code: -.. io-code-block:: - :copyable: true +.. tabs:: + + .. tab:: Synchronous + :tabid: sync - .. input:: - :language: python + .. io-code-block:: + :copyable: true - from datetime import datetime + .. input:: + :language: python - collection = database["sample_collection"] - find_result = collection.find_one()["date"] - print(f"datetime: {find_result}") - print(f"datetime.tzinfo: {find_result.tzinfo}") + from datetime import datetime - .. output:: - :language: shell - :visible: false + collection = database["sample_collection"] + find_result = collection.find_one()["date"] + print(f"datetime: {find_result}") + print(f"datetime.tzinfo: {find_result.tzinfo}") + + .. output:: + :language: shell + :visible: false + + datetime: 2002-10-27 14:00:00 + datetime.tzinfo: None + + .. tab:: Asynchronous + :tabid: async + + .. io-code-block:: + :copyable: true - datetime: 2002-10-27 14:00:00 - datetime.tzinfo: None + .. input:: + :language: python + + from datetime import datetime + + collection = database["sample_collection"] + find_result = (await collection.find_one())["date"] + print(f"datetime: {find_result}") + print(f"datetime.tzinfo: {find_result.tzinfo}") + + .. output:: + :language: shell + :visible: false + + datetime: 2002-10-27 14:00:00 + datetime.tzinfo: None Aware UTC datetime ~~~~~~~~~~~~~~~~~~ @@ -154,31 +183,65 @@ create a ``CodecOptions`` object and pass ``tz_aware = True`` to the constructor Then, pass the ``CodecOptions`` object to the ``get_collection()`` method. The following code example retrieves the ``datetime`` value from the sample document as -an aware ``datetime``: +an aware ``datetime``. Select the :guilabel:`Synchronous` or :guilabel:`Asynchronous` tab +to see the corresponding code: -.. io-code-block:: - :copyable: true +.. tabs:: + + .. tab:: Synchronous + :tabid: sync - .. input:: - :language: python + .. io-code-block:: + :copyable: true - from pymongo import MongoClient - from datetime import datetime - from bson.codec_options import CodecOptions + .. input:: + :language: python + + from pymongo import MongoClient + from datetime import datetime + from bson.codec_options import CodecOptions - options = CodecOptions(tz_aware = True) - collection = database.get_collection("sample_collection", options) - find_result = collection.find_one()["date"] + options = CodecOptions(tz_aware = True) + collection = database.get_collection("sample_collection", options) + find_result = collection.find_one()["date"] + + print(f"datetime: {find_result}") + print(f"datetime.tzinfo: {find_result.tzinfo}") + + .. output:: + :language: shell + :visible: false + + datetime: 2002-10-27 14:00:00+00:00 + datetime.tzinfo: + + .. tab:: Asynchronous + :tabid: async - print(f"datetime: {find_result}") - print(f"datetime.tzinfo: {find_result.tzinfo}") + .. io-code-block:: + :copyable: true - .. output:: - :language: shell - :visible: false + .. input:: + :language: python + + from pymongo import MongoClient + from datetime import datetime + from bson.codec_options import CodecOptions + + options = CodecOptions(tz_aware = True) + collection = database.get_collection("sample_collection", options) + find_result = (await collection.find_one())["date"] + + print(f"datetime: {find_result}") + print(f"datetime.tzinfo: {find_result.tzinfo}") + + .. output:: + :language: shell + :visible: false + + datetime: 2002-10-27 14:00:00+00:00 + datetime.tzinfo: - datetime: 2002-10-27 14:00:00+00:00 - datetime.tzinfo: Localized datetime ~~~~~~~~~~~~~~~~~~ @@ -194,34 +257,70 @@ Then, create a ``CodecOptions`` object and pass the following arguments to the c The following code example retrieves the sample document, but uses the ``tz_aware`` and ``tzinfo`` arguments to automatically localize -the ``datetime`` value to the ``"US/Pacific"`` time zone: - -.. io-code-block:: - :copyable: true +the ``datetime`` value to the ``"US/Pacific"`` time zone. Select the :guilabel:`Synchronous` +or :guilabel:`Asynchronous` tab to see the corresponding code: - .. input:: - :language: python - - from pymongo import MongoClient - from datetime import datetime - from bson.codec_options import CodecOptions - import pytz - from pytz import timezone - - pacific = timezone("US/Pacific") - options = CodecOptions(tz_aware = True, tzinfo = pacific) - collection = database.get_collection("sample_collection", options) - - find_result = collection.find_one()["date"] - print(f"datetime: {find_result}") - print(f"datetime.tzinfo: {find_result.tzinfo}") +.. tabs:: - .. output:: - :language: shell - :visible: false - - datetime: 2002-10-27 06:00:00-08:00 - datetime.tzinfo: US/Pacific + .. tab:: Synchronous + :tabid: sync + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + from pymongo import MongoClient + from datetime import datetime + from bson.codec_options import CodecOptions + import pytz + from pytz import timezone + + pacific = timezone("US/Pacific") + options = CodecOptions(tz_aware = True, tzinfo = pacific) + collection = database.get_collection("sample_collection", options) + + find_result = collection.find_one()["date"] + print(f"datetime: {find_result}") + print(f"datetime.tzinfo: {find_result.tzinfo}") + + .. output:: + :language: shell + :visible: false + + datetime: 2002-10-27 06:00:00-08:00 + datetime.tzinfo: US/Pacific + + .. tab:: Asynchronous + :tabid: async + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + from pymongo import MongoClient + from datetime import datetime + from bson.codec_options import CodecOptions + import pytz + from pytz import timezone + + pacific = timezone("US/Pacific") + options = CodecOptions(tz_aware = True, tzinfo = pacific) + collection = database.get_collection("sample_collection", options) + + find_result = (await collection.find_one())["date"] + print(f"datetime: {find_result}") + print(f"datetime.tzinfo: {find_result.tzinfo}") + + .. output:: + :language: shell + :visible: false + + datetime: 2002-10-27 06:00:00-08:00 + datetime.tzinfo: US/Pacific .. tip:: @@ -243,33 +342,69 @@ whether the ``datetime`` value is naive or aware: The following code example inserts a document containing a ``datetime`` value localized to the ``"US/Pacific"`` time zone. {+driver-short+} uses the attached time zone to convert the local time to UTC. When the document is retrieved from MongoDB, the ``datetime`` value -is in UTC. +is in UTC. Select the :guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the +corresponding code: -.. io-code-block:: - :copyable: true +.. tabs:: + + .. tab:: Synchronous + :tabid: sync + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + from pymongo import MongoClient + from datetime import datetime + from pytz import timezone + + utc_datetime = datetime(2002, 10, 27, 6, 0, 0) + pacific = timezone("US/Pacific") + local_datetime = pacific.localize(utc_datetime) + + print(f"datetime before storage: {local_datetime}") + collection.insert_one({"date": local_datetime}) + find_result = collection.find_one()["date"] + print(f"datetime after storage: {find_result}") + + .. output:: + :language: shell + :visible: false + + datetime before storage: 2002-10-27 06:00:00-08:00 + datetime after storage: 2002-10-27 14:00:00 + + .. tab:: Asynchronous + :tabid: async - .. input:: - :language: python + .. io-code-block:: + :copyable: true - from pymongo import MongoClient - from datetime import datetime - from pytz import timezone - - utc_datetime = datetime(2002, 10, 27, 6, 0, 0) - pacific = timezone("US/Pacific") - local_datetime = pacific.localize(utc_datetime) + .. input:: + :language: python - print(f"datetime before storage: {local_datetime}") - collection.insert_one({"date": local_datetime}) - find_result = collection.find_one()["date"] - print(f"datetime after storage: {find_result}") + from pymongo import MongoClient + from datetime import datetime + from pytz import timezone + + utc_datetime = datetime(2002, 10, 27, 6, 0, 0) + pacific = timezone("US/Pacific") + local_datetime = pacific.localize(utc_datetime) - .. output:: - :language: shell - :visible: false + print(f"datetime before storage: {local_datetime}") + await collection.insert_one({"date": local_datetime}) + find_result = (await collection.find_one())["date"] + print(f"datetime after storage: {find_result}") + + .. output:: + :language: shell + :visible: false + + datetime before storage: 2002-10-27 06:00:00-08:00 + datetime after storage: 2002-10-27 14:00:00 - datetime before storage: 2002-10-27 06:00:00-08:00 - datetime after storage: 2002-10-27 14:00:00 .. important:: datetime.now() @@ -465,30 +600,62 @@ attempt to decode the value as a ``datetime.datetime``, allowing ``~bson.codec_options.DatetimeConversion.DATETIME_AUTO`` alters this behavior to instead return ``~bson.datetime_ms.DatetimeMS`` when representations are out-of-range, while returning ``~datetime.datetime`` -objects as before: +objects as before. Select the :guilabel:`Synchronous` +or :guilabel:`Asynchronous` tab to see the corresponding code: -.. io-code-block:: +.. tabs:: + + .. tab:: Synchronous + :tabid: sync - .. input:: - :language: python + .. io-code-block:: - from datetime import datetime - from bson.datetime_ms import DatetimeMS - from bson.codec_options import DatetimeConversion - from pymongo import MongoClient + .. input:: + :language: python - client = MongoClient(datetime_conversion=DatetimeConversion.DATETIME_AUTO) - client.db.collection.insert_one({"x": datetime(1970, 1, 1)}) + from datetime import datetime + from bson.datetime_ms import DatetimeMS + from bson.codec_options import DatetimeConversion + from pymongo import MongoClient - client.db.collection.insert_one({"x": DatetimeMS(2**62)}) + client = MongoClient(datetime_conversion=DatetimeConversion.DATETIME_AUTO) + client.db.collection.insert_one({"x": datetime(1970, 1, 1)}) - for x in client.db.collection.find(): - print(x) - - .. output:: + client.db.collection.insert_one({"x": DatetimeMS(2**62)}) + + for x in client.db.collection.find(): + print(x) + + .. output:: + + {'_id': ObjectId('...'), 'x': datetime.datetime(1970, 1, 1, 0, 0)} + {'_id': ObjectId('...'), 'x': DatetimeMS(4611686018427387904)} + + .. tab:: Asynchronous + :tabid: async + + .. io-code-block:: + + .. input:: + :language: python - {'_id': ObjectId('...'), 'x': datetime.datetime(1970, 1, 1, 0, 0)} - {'_id': ObjectId('...'), 'x': DatetimeMS(4611686018427387904)} + from datetime import datetime + from bson.datetime_ms import DatetimeMS + from bson.codec_options import DatetimeConversion + from pymongo import MongoClient + + client = AsyncMongoClient(datetime_conversion=DatetimeConversion.DATETIME_AUTO) + await client.db.collection.insert_one({"x": datetime(1970, 1, 1)}) + + await client.db.collection.insert_one({"x": DatetimeMS(2**62)}) + + async for x in client.db.collection.find(): + print(x) + + .. output:: + + {'_id': ObjectId('...'), 'x': datetime.datetime(1970, 1, 1, 0, 0)} + {'_id': ObjectId('...'), 'x': DatetimeMS(4611686018427387904)} For other options, see the API documentation for the `DatetimeConversion <{+api-root+}bson/codec_options.html#bson.codec_options.DatetimeConversion>`__ @@ -496,19 +663,47 @@ class. Another option that does not involve setting ``datetime_conversion`` is to filter out document values outside of the range supported by -``~datetime.datetime``: +``~datetime.datetime``. Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: -.. code-block:: python +.. tabs:: + + .. tab:: Synchronous + :tabid: sync - from datetime import datetime - coll = client.test.dates - cur = coll.find({'dt': {'$gte': datetime.min, '$lte': datetime.max}}) + .. code-block:: python -If you don't need the value of ``datetime``, you can filter out just that field: + from datetime import datetime + coll = client.test.dates + cur = coll.find({'dt': {'$gte': datetime.min, '$lte': datetime.max}}) -.. code-block:: python + .. tab:: Asynchronous + :tabid: async + + .. code-block:: python + + from datetime import datetime + coll = client.test.dates + cur = coll.find({'dt': {'$gte': datetime.min, '$lte': datetime.max}}) + +If you don't need the value of ``datetime``, you can filter out just that field. Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: + +.. tabs:: + + .. tab:: Synchronous + :tabid: sync + + .. code-block:: python + + cur = coll.find({}, projection={'dt': False}) + + .. tab:: Asynchronous + :tabid: async + + .. code-block:: python - cur = coll.find({}, projection={'dt': False}) + cur = coll.find({}, projection={'dt': False}) API Documentation ----------------- diff --git a/source/data-formats/time-series.txt b/source/data-formats/time-series.txt index 7e7e7b6d..f553f829 100644 --- a/source/data-formats/time-series.txt +++ b/source/data-formats/time-series.txt @@ -83,47 +83,104 @@ Example ~~~~~~~ The following example creates a time series collection named ``october2024`` with the -``timeField`` option set to ``"timestamp"``: +``timeField`` option set to ``"timestamp"``. Select the :guilabel:`Synchronous` +or :guilabel:`Asynchronous` tab to see the corresponding code: -.. code-block:: python +.. tabs:: + + .. tab:: Synchronous + :tabid: sync - database = client.get_database("weather") + .. code-block:: python - time_series_options = { - "timeField": "timestamp" - } + database = client.get_database("weather") + + time_series_options = { + "timeField": "timestamp" + } + + database.create_collection("october2024", timeseries=time_series_options) + + .. tab:: Asynchronous + :tabid: async + + .. code-block:: python + + database = client.get_database("weather") + + time_series_options = { + "timeField": "timestamp" + } + + await database.create_collection("october2024", timeseries=time_series_options) - database.create_collection("october2024", timeseries=time_series_options) To check if you successfully created the collection, you can get a list of all -collections in your database and filter by collection name: - -.. io-code-block:: - :copyable: true - - .. input:: - :language: python - - print(list(database.list_collections(filter={'name': 'october2024'}))) - - .. output:: - :language: json - :visible: false - - { - "name": "october2024", - "type": "timeseries", - "options": { - "timeseries": { - "timeField": "timestamp", - "granularity": "seconds", - "bucketMaxSpanSeconds": 3600 - } - }, - "info": { - "readOnly": False - } - } +collections in your database and filter by collection name. Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: + +.. tabs:: + + .. tab:: Synchronous + :tabid: sync + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + print(list(database.list_collections(filter={'name': 'october2024'}))) + + .. output:: + :language: json + :visible: false + + { + "name": "october2024", + "type": "timeseries", + "options": { + "timeseries": { + "timeField": "timestamp", + "granularity": "seconds", + "bucketMaxSpanSeconds": 3600 + } + }, + "info": { + "readOnly": False + } + } + + .. tab:: Asynchronous + :tabid: async + + .. io-code-block:: + :copyable: true + + .. input:: + :language: python + + collections = await database.list_collections(filter={'name': 'october2024'}) + print(await collections.to_list()) + + .. output:: + :language: json + :visible: false + + { + "name": "october2024", + "type": "timeseries", + "options": { + "timeseries": { + "timeField": "timestamp", + "granularity": "seconds", + "bucketMaxSpanSeconds": 3600 + } + }, + "info": { + "readOnly": False + } + } .. _pymongo-time-series-write: @@ -147,18 +204,42 @@ document contains the following fields: - ``location``, which stores location metadata - ``timestamp``, which stores the measurement timestamp -.. code-block:: python +Select the +:guilabel:`Synchronous` or :guilabel:`Asynchronous` tab to see the corresponding code: + +.. tabs:: + + .. tab:: Synchronous + :tabid: sync + + .. code-block:: python + + from datetime import datetime + + collection = database["october2024"] + + document_list = [ + { "temperature": 77, "location": "New York City", "timestamp": datetime(2024, 10, 22, 6, 0, 0) }, + { "temperature": 74, "location": "New York City", "timestamp": datetime(2024, 10, 23, 6, 0, 0) } + ] + + collection.insert_many(document_list) + + .. tab:: Asynchronous + :tabid: async + + .. code-block:: python - from datetime import datetime + from datetime import datetime - collection = database["october2024"] + collection = database["october2024"] - document_list = [ - { "temperature": 77, "location": "New York City", "timestamp": datetime(2024, 10, 22, 6, 0, 0) }, - { "temperature": 74, "location": "New York City", "timestamp": datetime(2024, 10, 23, 6, 0, 0) } - ] + document_list = [ + { "temperature": 77, "location": "New York City", "timestamp": datetime(2024, 10, 22, 6, 0, 0) }, + { "temperature": 74, "location": "New York City", "timestamp": datetime(2024, 10, 23, 6, 0, 0) } + ] - collection.insert_many(document_list) + await collection.insert_many(document_list) .. tip:: Formatting Dates and Times