PYTHON-3610 Add blacken-docs to pre-commit hook (#1170)
This commit is contained in:
parent
25ba21770c
commit
e9a6482c4d
@ -30,6 +30,13 @@ repos:
|
||||
files: \.py$
|
||||
args: [--profile=black]
|
||||
|
||||
- repo: https://github.com/adamchainz/blacken-docs
|
||||
rev: "1.13.0"
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies:
|
||||
- black==22.3.0
|
||||
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 3.9.2
|
||||
hooks:
|
||||
|
||||
@ -148,7 +148,7 @@ Examples
|
||||
========
|
||||
Here's a basic example (for more see the *examples* section of the docs):
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> import pymongo
|
||||
>>> client = pymongo.MongoClient("localhost", 27017)
|
||||
|
||||
@ -29,7 +29,9 @@ Example usage (deserialization):
|
||||
.. doctest::
|
||||
|
||||
>>> from bson.json_util import loads
|
||||
>>> loads('[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$scope": {}, "$code": "function x() { return 1; }"}}, {"bin": {"$type": "80", "$binary": "AQIDBA=="}}]')
|
||||
>>> loads(
|
||||
... '[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$scope": {}, "$code": "function x() { return 1; }"}}, {"bin": {"$type": "80", "$binary": "AQIDBA=="}}]'
|
||||
... )
|
||||
[{'foo': [1, 2]}, {'bar': {'hello': 'world'}}, {'code': Code('function x() { return 1; }', {})}, {'bin': Binary(b'...', 128)}]
|
||||
|
||||
Example usage with :const:`RELAXED_JSON_OPTIONS` (the default):
|
||||
@ -38,10 +40,14 @@ Example usage with :const:`RELAXED_JSON_OPTIONS` (the default):
|
||||
|
||||
>>> from bson import Binary, Code
|
||||
>>> from bson.json_util import dumps
|
||||
>>> dumps([{'foo': [1, 2]},
|
||||
... {'bar': {'hello': 'world'}},
|
||||
... {'code': Code("function x() { return 1; }")},
|
||||
... {'bin': Binary(b"\x01\x02\x03\x04")}])
|
||||
>>> dumps(
|
||||
... [
|
||||
... {"foo": [1, 2]},
|
||||
... {"bar": {"hello": "world"}},
|
||||
... {"code": Code("function x() { return 1; }")},
|
||||
... {"bin": Binary(b"\x01\x02\x03\x04")},
|
||||
... ]
|
||||
... )
|
||||
'[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]'
|
||||
|
||||
Example usage (with :const:`CANONICAL_JSON_OPTIONS`):
|
||||
@ -50,11 +56,15 @@ Example usage (with :const:`CANONICAL_JSON_OPTIONS`):
|
||||
|
||||
>>> from bson import Binary, Code
|
||||
>>> from bson.json_util import dumps, CANONICAL_JSON_OPTIONS
|
||||
>>> dumps([{'foo': [1, 2]},
|
||||
... {'bar': {'hello': 'world'}},
|
||||
... {'code': Code("function x() { return 1; }")},
|
||||
... {'bin': Binary(b"\x01\x02\x03\x04")}],
|
||||
... json_options=CANONICAL_JSON_OPTIONS)
|
||||
>>> dumps(
|
||||
... [
|
||||
... {"foo": [1, 2]},
|
||||
... {"bar": {"hello": "world"}},
|
||||
... {"code": Code("function x() { return 1; }")},
|
||||
... {"bin": Binary(b"\x01\x02\x03\x04")},
|
||||
... ],
|
||||
... json_options=CANONICAL_JSON_OPTIONS,
|
||||
... )
|
||||
'[{"foo": [{"$numberInt": "1"}, {"$numberInt": "2"}]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }"}}, {"bin": {"$binary": {"base64": "AQIDBA==", "subType": "00"}}}]'
|
||||
|
||||
Example usage (with :const:`LEGACY_JSON_OPTIONS`):
|
||||
@ -63,11 +73,15 @@ Example usage (with :const:`LEGACY_JSON_OPTIONS`):
|
||||
|
||||
>>> from bson import Binary, Code
|
||||
>>> from bson.json_util import dumps, LEGACY_JSON_OPTIONS
|
||||
>>> dumps([{'foo': [1, 2]},
|
||||
... {'bar': {'hello': 'world'}},
|
||||
... {'code': Code("function x() { return 1; }", {})},
|
||||
... {'bin': Binary(b"\x01\x02\x03\x04")}],
|
||||
... json_options=LEGACY_JSON_OPTIONS)
|
||||
>>> dumps(
|
||||
... [
|
||||
... {"foo": [1, 2]},
|
||||
... {"bar": {"hello": "world"}},
|
||||
... {"code": Code("function x() { return 1; }", {})},
|
||||
... {"bin": Binary(b"\x01\x02\x03\x04")},
|
||||
... ],
|
||||
... json_options=LEGACY_JSON_OPTIONS,
|
||||
... )
|
||||
'[{"foo": [1, 2]}, {"bar": {"hello": "world"}}, {"code": {"$code": "function x() { return 1; }", "$scope": {}}}, {"bin": {"$binary": "AQIDBA==", "$type": "00"}}]'
|
||||
|
||||
Alternatively, you can manually pass the `default` to :func:`json.dumps`.
|
||||
|
||||
@ -25,18 +25,18 @@ Example: Moving a document between different databases/collections
|
||||
>>> from pymongo import MongoClient
|
||||
>>> from bson.raw_bson import RawBSONDocument
|
||||
>>> client = MongoClient(document_class=RawBSONDocument)
|
||||
>>> client.drop_database('db')
|
||||
>>> client.drop_database('replica_db')
|
||||
>>> client.drop_database("db")
|
||||
>>> client.drop_database("replica_db")
|
||||
>>> db = client.db
|
||||
>>> result = db.test.insert_many([{'_id': 1, 'a': 1},
|
||||
... {'_id': 2, 'b': 1},
|
||||
... {'_id': 3, 'c': 1},
|
||||
... {'_id': 4, 'd': 1}])
|
||||
>>> result = db.test.insert_many(
|
||||
... [{"_id": 1, "a": 1}, {"_id": 2, "b": 1}, {"_id": 3, "c": 1}, {"_id": 4, "d": 1}]
|
||||
... )
|
||||
>>> replica_db = client.replica_db
|
||||
>>> for doc in db.test.find():
|
||||
... print(f"raw document: {doc.raw}")
|
||||
... print(f"decoded document: {bson.decode(doc.raw)}")
|
||||
... result = replica_db.test.insert_one(doc)
|
||||
... print(f"raw document: {doc.raw}")
|
||||
... print(f"decoded document: {bson.decode(doc.raw)}")
|
||||
... result = replica_db.test.insert_one(doc)
|
||||
...
|
||||
raw document: b'...'
|
||||
decoded document: {'_id': 1, 'a': 1}
|
||||
raw document: b'...'
|
||||
|
||||
@ -8,8 +8,9 @@ group method.
|
||||
.. testsetup::
|
||||
|
||||
from pymongo import MongoClient
|
||||
|
||||
client = MongoClient()
|
||||
client.drop_database('aggregation_example')
|
||||
client.drop_database("aggregation_example")
|
||||
|
||||
Setup
|
||||
-----
|
||||
@ -20,10 +21,14 @@ aggregations on:
|
||||
|
||||
>>> from pymongo import MongoClient
|
||||
>>> db = MongoClient().aggregation_example
|
||||
>>> result = db.things.insert_many([{"x": 1, "tags": ["dog", "cat"]},
|
||||
... {"x": 2, "tags": ["cat"]},
|
||||
... {"x": 2, "tags": ["mouse", "cat", "dog"]},
|
||||
... {"x": 3, "tags": []}])
|
||||
>>> result = db.things.insert_many(
|
||||
... [
|
||||
... {"x": 1, "tags": ["dog", "cat"]},
|
||||
... {"x": 2, "tags": ["cat"]},
|
||||
... {"x": 2, "tags": ["mouse", "cat", "dog"]},
|
||||
... {"x": 3, "tags": []},
|
||||
... ]
|
||||
... )
|
||||
>>> result.inserted_ids
|
||||
[ObjectId('...'), ObjectId('...'), ObjectId('...'), ObjectId('...')]
|
||||
|
||||
@ -54,7 +59,7 @@ eg "$sort":
|
||||
>>> pipeline = [
|
||||
... {"$unwind": "$tags"},
|
||||
... {"$group": {"_id": "$tags", "count": {"$sum": 1}}},
|
||||
... {"$sort": SON([("count", -1), ("_id", -1)])}
|
||||
... {"$sort": SON([("count", -1), ("_id", -1)])},
|
||||
... ]
|
||||
>>> import pprint
|
||||
>>> pprint.pprint(list(db.things.aggregate(pipeline)))
|
||||
|
||||
@ -4,8 +4,9 @@ Bulk Write Operations
|
||||
.. testsetup::
|
||||
|
||||
from pymongo import MongoClient
|
||||
|
||||
client = MongoClient()
|
||||
client.drop_database('bulk_example')
|
||||
client.drop_database("bulk_example")
|
||||
|
||||
This tutorial explains how to take advantage of PyMongo's bulk
|
||||
write operation features. Executing write operations in batches
|
||||
@ -27,7 +28,7 @@ bulk insert operations.
|
||||
|
||||
>>> import pymongo
|
||||
>>> db = pymongo.MongoClient().bulk_example
|
||||
>>> db.test.insert_many([{'i': i} for i in range(10000)]).inserted_ids
|
||||
>>> db.test.insert_many([{"i": i} for i in range(10000)]).inserted_ids
|
||||
[...]
|
||||
>>> db.test.count_documents({})
|
||||
10000
|
||||
@ -56,14 +57,17 @@ of operations performed.
|
||||
|
||||
>>> from pprint import pprint
|
||||
>>> from pymongo import InsertOne, DeleteMany, ReplaceOne, UpdateOne
|
||||
>>> result = db.test.bulk_write([
|
||||
... DeleteMany({}), # Remove all documents from the previous example.
|
||||
... InsertOne({'_id': 1}),
|
||||
... InsertOne({'_id': 2}),
|
||||
... InsertOne({'_id': 3}),
|
||||
... UpdateOne({'_id': 1}, {'$set': {'foo': 'bar'}}),
|
||||
... UpdateOne({'_id': 4}, {'$inc': {'j': 1}}, upsert=True),
|
||||
... ReplaceOne({'j': 1}, {'j': 2})])
|
||||
>>> result = db.test.bulk_write(
|
||||
... [
|
||||
... DeleteMany({}), # Remove all documents from the previous example.
|
||||
... InsertOne({"_id": 1}),
|
||||
... InsertOne({"_id": 2}),
|
||||
... InsertOne({"_id": 3}),
|
||||
... UpdateOne({"_id": 1}, {"$set": {"foo": "bar"}}),
|
||||
... UpdateOne({"_id": 4}, {"$inc": {"j": 1}}, upsert=True),
|
||||
... ReplaceOne({"j": 1}, {"j": 2}),
|
||||
... ]
|
||||
... )
|
||||
>>> pprint(result.bulk_api_result)
|
||||
{'nInserted': 3,
|
||||
'nMatched': 2,
|
||||
@ -87,9 +91,10 @@ the failure.
|
||||
>>> from pymongo import InsertOne, DeleteOne, ReplaceOne
|
||||
>>> from pymongo.errors import BulkWriteError
|
||||
>>> requests = [
|
||||
... ReplaceOne({'j': 2}, {'i': 5}),
|
||||
... InsertOne({'_id': 4}), # Violates the unique key constraint on _id.
|
||||
... DeleteOne({'i': 5})]
|
||||
... ReplaceOne({"j": 2}, {"i": 5}),
|
||||
... InsertOne({"_id": 4}), # Violates the unique key constraint on _id.
|
||||
... DeleteOne({"i": 5}),
|
||||
... ]
|
||||
>>> try:
|
||||
... db.test.bulk_write(requests)
|
||||
... except BulkWriteError as bwe:
|
||||
@ -124,10 +129,11 @@ and fourth operations succeed.
|
||||
:options: +NORMALIZE_WHITESPACE
|
||||
|
||||
>>> requests = [
|
||||
... InsertOne({'_id': 1}),
|
||||
... DeleteOne({'_id': 2}),
|
||||
... InsertOne({'_id': 3}),
|
||||
... ReplaceOne({'_id': 4}, {'i': 1})]
|
||||
... InsertOne({"_id": 1}),
|
||||
... DeleteOne({"_id": 2}),
|
||||
... InsertOne({"_id": 3}),
|
||||
... ReplaceOne({"_id": 4}, {"i": 1}),
|
||||
... ]
|
||||
>>> try:
|
||||
... db.test.bulk_write(requests, ordered=False)
|
||||
... except BulkWriteError as bwe:
|
||||
|
||||
@ -19,7 +19,7 @@ We'll start by getting a clean database to use for the example:
|
||||
|
||||
>>> from pymongo import MongoClient
|
||||
>>> client = MongoClient()
|
||||
>>> client.drop_database('custom_type_example')
|
||||
>>> client.drop_database("custom_type_example")
|
||||
>>> db = client.custom_type_example
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ to save an instance of ``Decimal`` with PyMongo, results in an
|
||||
|
||||
>>> from decimal import Decimal
|
||||
>>> num = Decimal("45.321")
|
||||
>>> db.test.insert_one({'num': num})
|
||||
>>> db.test.insert_one({"num": num})
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), of type: <class 'decimal.Decimal'>
|
||||
@ -78,8 +78,8 @@ interested in both encoding and decoding our custom type, we use the
|
||||
>>> from bson.decimal128 import Decimal128
|
||||
>>> from bson.codec_options import TypeCodec
|
||||
>>> class DecimalCodec(TypeCodec):
|
||||
... python_type = Decimal # the Python type acted upon by this type codec
|
||||
... bson_type = Decimal128 # the BSON type acted upon by this type codec
|
||||
... python_type = Decimal # the Python type acted upon by this type codec
|
||||
... bson_type = Decimal128 # the BSON type acted upon by this type codec
|
||||
... def transform_python(self, value):
|
||||
... """Function that transforms a custom type value into a type
|
||||
... that BSON can encode."""
|
||||
@ -88,6 +88,7 @@ interested in both encoding and decoding our custom type, we use the
|
||||
... """Function that transforms a vanilla BSON type value into our
|
||||
... custom type."""
|
||||
... return value.to_decimal()
|
||||
...
|
||||
>>> decimal_codec = DecimalCodec()
|
||||
|
||||
|
||||
@ -125,7 +126,7 @@ with our ``type_registry`` and use it to get a
|
||||
|
||||
>>> from bson.codec_options import CodecOptions
|
||||
>>> codec_options = CodecOptions(type_registry=type_registry)
|
||||
>>> collection = db.get_collection('test', codec_options=codec_options)
|
||||
>>> collection = db.get_collection("test", codec_options=codec_options)
|
||||
|
||||
|
||||
Now, we can seamlessly encode and decode instances of
|
||||
@ -133,7 +134,7 @@ Now, we can seamlessly encode and decode instances of
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> collection.insert_one({'num': Decimal("45.321")})
|
||||
>>> collection.insert_one({"num": Decimal("45.321")})
|
||||
<pymongo.results.InsertOneResult object at ...>
|
||||
>>> mydoc = collection.find_one()
|
||||
>>> import pprint
|
||||
@ -147,7 +148,7 @@ MongoDB:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> vanilla_collection = db.get_collection('test')
|
||||
>>> vanilla_collection = db.get_collection("test")
|
||||
>>> pprint.pprint(vanilla_collection.find_one())
|
||||
{'_id': ObjectId('...'), 'num': Decimal128('45.321')}
|
||||
|
||||
@ -170,13 +171,14 @@ an integer:
|
||||
... def my_method(self):
|
||||
... """Method implementing some custom logic."""
|
||||
... return int(self)
|
||||
...
|
||||
|
||||
If we try to save an instance of this type without first registering a type
|
||||
codec for it, we get an error:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> collection.insert_one({'num': DecimalInt("45.321")})
|
||||
>>> collection.insert_one({"num": DecimalInt("45.321")})
|
||||
Traceback (most recent call last):
|
||||
...
|
||||
bson.errors.InvalidDocument: cannot encode object: Decimal('45.321'), of type: <class 'decimal.Decimal'>
|
||||
@ -192,6 +194,7 @@ This is trivial to do since the same transformation as the one used for
|
||||
... def python_type(self):
|
||||
... """The Python type acted upon by this type codec."""
|
||||
... return DecimalInt
|
||||
...
|
||||
>>> decimalint_codec = DecimalIntCodec()
|
||||
|
||||
|
||||
@ -211,9 +214,9 @@ object, we can seamlessly encode instances of ``DecimalInt``:
|
||||
|
||||
>>> type_registry = TypeRegistry([decimal_codec, decimalint_codec])
|
||||
>>> codec_options = CodecOptions(type_registry=type_registry)
|
||||
>>> collection = db.get_collection('test', codec_options=codec_options)
|
||||
>>> collection = db.get_collection("test", codec_options=codec_options)
|
||||
>>> collection.drop()
|
||||
>>> collection.insert_one({'num': DecimalInt("45.321")})
|
||||
>>> collection.insert_one({"num": DecimalInt("45.321")})
|
||||
<pymongo.results.InsertOneResult object at ...>
|
||||
>>> mydoc = collection.find_one()
|
||||
>>> pprint.pprint(mydoc)
|
||||
@ -236,26 +239,26 @@ writing a ``TypeDecoder`` that modifies how this datatype is decoded.
|
||||
On Python 3.x, :class:`~bson.binary.Binary` data (``subtype = 0``) is decoded
|
||||
as a ``bytes`` instance:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # On Python 3.x.
|
||||
>>> from bson.binary import Binary
|
||||
>>> newcoll = db.get_collection('new')
|
||||
>>> newcoll.insert_one({'_id': 1, 'data': Binary(b"123", subtype=0)})
|
||||
>>> newcoll = db.get_collection("new")
|
||||
>>> newcoll.insert_one({"_id": 1, "data": Binary(b"123", subtype=0)})
|
||||
>>> doc = newcoll.find_one()
|
||||
>>> type(doc['data'])
|
||||
>>> type(doc["data"])
|
||||
bytes
|
||||
|
||||
|
||||
On Python 2.7.x, the same data is decoded as a :class:`~bson.binary.Binary`
|
||||
instance:
|
||||
|
||||
.. code-block:: python
|
||||
.. code-block:: pycon
|
||||
|
||||
>>> # On Python 2.7.x
|
||||
>>> newcoll = db.get_collection('new')
|
||||
>>> newcoll = db.get_collection("new")
|
||||
>>> doc = newcoll.find_one()
|
||||
>>> type(doc['data'])
|
||||
>>> type(doc["data"])
|
||||
bson.binary.Binary
|
||||
|
||||
|
||||
@ -291,6 +294,7 @@ BSON-encodable value. The following fallback encoder encodes python's
|
||||
... if isinstance(value, Decimal):
|
||||
... return Decimal128(value)
|
||||
... return value
|
||||
...
|
||||
|
||||
After declaring the callback, we must create a type registry and codec options
|
||||
with this fallback encoder before it can be used for initializing a collection:
|
||||
@ -299,14 +303,14 @@ with this fallback encoder before it can be used for initializing a collection:
|
||||
|
||||
>>> type_registry = TypeRegistry(fallback_encoder=fallback_encoder)
|
||||
>>> codec_options = CodecOptions(type_registry=type_registry)
|
||||
>>> collection = db.get_collection('test', codec_options=codec_options)
|
||||
>>> collection = db.get_collection("test", codec_options=codec_options)
|
||||
>>> collection.drop()
|
||||
|
||||
We can now seamlessly encode instances of :py:class:`~decimal.Decimal`:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> collection.insert_one({'num': Decimal("45.321")})
|
||||
>>> collection.insert_one({"num": Decimal("45.321")})
|
||||
<pymongo.results.InsertOneResult object at ...>
|
||||
>>> mydoc = collection.find_one()
|
||||
>>> pprint.pprint(mydoc)
|
||||
@ -343,12 +347,15 @@ We start by defining some arbitrary custom types:
|
||||
class MyStringType(object):
|
||||
def __init__(self, value):
|
||||
self.__value = value
|
||||
|
||||
def __repr__(self):
|
||||
return "MyStringType('%s')" % (self.__value,)
|
||||
|
||||
|
||||
class MyNumberType(object):
|
||||
def __init__(self, value):
|
||||
self.__value = value
|
||||
|
||||
def __repr__(self):
|
||||
return "MyNumberType(%s)" % (self.__value,)
|
||||
|
||||
@ -362,11 +369,15 @@ back into Python objects:
|
||||
|
||||
import pickle
|
||||
from bson.binary import Binary, USER_DEFINED_SUBTYPE
|
||||
|
||||
|
||||
def fallback_pickle_encoder(value):
|
||||
return Binary(pickle.dumps(value), USER_DEFINED_SUBTYPE)
|
||||
|
||||
|
||||
class PickledBinaryDecoder(TypeDecoder):
|
||||
bson_type = Binary
|
||||
|
||||
def transform_bson(self, value):
|
||||
if value.subtype == USER_DEFINED_SUBTYPE:
|
||||
return pickle.loads(value)
|
||||
@ -384,19 +395,23 @@ Finally, we create a ``CodecOptions`` instance:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
codec_options = CodecOptions(type_registry=TypeRegistry(
|
||||
[PickledBinaryDecoder()], fallback_encoder=fallback_pickle_encoder))
|
||||
codec_options = CodecOptions(
|
||||
type_registry=TypeRegistry(
|
||||
[PickledBinaryDecoder()], fallback_encoder=fallback_pickle_encoder
|
||||
)
|
||||
)
|
||||
|
||||
We can now round trip our custom objects to MongoDB:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
collection = db.get_collection('test_fe', codec_options=codec_options)
|
||||
collection.insert_one({'_id': 1, 'str': MyStringType("hello world"),
|
||||
'num': MyNumberType(2)})
|
||||
collection = db.get_collection("test_fe", codec_options=codec_options)
|
||||
collection.insert_one(
|
||||
{"_id": 1, "str": MyStringType("hello world"), "num": MyNumberType(2)}
|
||||
)
|
||||
mydoc = collection.find_one()
|
||||
assert isinstance(mydoc['str'], MyStringType)
|
||||
assert isinstance(mydoc['num'], MyNumberType)
|
||||
assert isinstance(mydoc["str"], MyStringType)
|
||||
assert isinstance(mydoc["num"], MyNumberType)
|
||||
|
||||
|
||||
Limitations
|
||||
|
||||
@ -6,8 +6,9 @@ Datetimes and Timezones
|
||||
import datetime
|
||||
from pymongo import MongoClient
|
||||
from bson.codec_options import CodecOptions
|
||||
|
||||
client = MongoClient()
|
||||
client.drop_database('dt_example')
|
||||
client.drop_database("dt_example")
|
||||
db = client.dt_example
|
||||
|
||||
These examples show how to handle Python :class:`datetime.datetime` objects
|
||||
@ -24,8 +25,7 @@ time into MongoDB:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> result = db.objects.insert_one(
|
||||
... {"last_modified": datetime.datetime.utcnow()})
|
||||
>>> result = db.objects.insert_one({"last_modified": datetime.datetime.utcnow()})
|
||||
|
||||
Always use :meth:`datetime.datetime.utcnow`, which returns the current time in
|
||||
UTC, instead of :meth:`datetime.datetime.now`, which returns the current local
|
||||
@ -33,8 +33,7 @@ time. Avoid doing this:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> result = db.objects.insert_one(
|
||||
... {"last_modified": datetime.datetime.now()})
|
||||
>>> result = db.objects.insert_one({"last_modified": datetime.datetime.now()})
|
||||
|
||||
The value for `last_modified` is very different between these two examples, even
|
||||
though both documents were stored at around the same local time. This will be
|
||||
@ -42,7 +41,7 @@ confusing to the application that reads them:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> [doc['last_modified'] for doc in db.objects.find()] # doctest: +SKIP
|
||||
>>> [doc["last_modified"] for doc in db.objects.find()] # doctest: +SKIP
|
||||
[datetime.datetime(2015, 7, 8, 18, 17, 28, 324000),
|
||||
datetime.datetime(2015, 7, 8, 11, 17, 42, 911000)]
|
||||
|
||||
@ -52,12 +51,11 @@ timezone they're in. By default, PyMongo retrieves naive datetimes:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> result = db.tzdemo.insert_one(
|
||||
... {'date': datetime.datetime(2002, 10, 27, 6, 0, 0)})
|
||||
>>> db.tzdemo.find_one()['date']
|
||||
>>> result = db.tzdemo.insert_one({"date": datetime.datetime(2002, 10, 27, 6, 0, 0)})
|
||||
>>> db.tzdemo.find_one()["date"]
|
||||
datetime.datetime(2002, 10, 27, 6, 0)
|
||||
>>> options = CodecOptions(tz_aware=True)
|
||||
>>> db.get_collection('tzdemo', codec_options=options).find_one()['date'] # doctest: +SKIP
|
||||
>>> db.get_collection("tzdemo", codec_options=options).find_one()["date"] # doctest: +SKIP
|
||||
datetime.datetime(2002, 10, 27, 6, 0,
|
||||
tzinfo=<bson.tz_util.FixedOffset object at 0x10583a050>)
|
||||
|
||||
@ -71,11 +69,10 @@ those datetimes to UTC automatically:
|
||||
.. doctest::
|
||||
|
||||
>>> import pytz
|
||||
>>> pacific = pytz.timezone('US/Pacific')
|
||||
>>> aware_datetime = pacific.localize(
|
||||
... datetime.datetime(2002, 10, 27, 6, 0, 0))
|
||||
>>> pacific = pytz.timezone("US/Pacific")
|
||||
>>> aware_datetime = pacific.localize(datetime.datetime(2002, 10, 27, 6, 0, 0))
|
||||
>>> result = db.times.insert_one({"date": aware_datetime})
|
||||
>>> db.times.find_one()['date']
|
||||
>>> db.times.find_one()["date"]
|
||||
datetime.datetime(2002, 10, 27, 14, 0)
|
||||
|
||||
Reading Time
|
||||
@ -150,7 +147,7 @@ cannot be represented using the builtin Python :class:`~datetime.datetime`:
|
||||
.. doctest::
|
||||
|
||||
>>> x = encode({"x": datetime(1970, 1, 1)})
|
||||
>>> y = encode({"x": DatetimeMS(-2**62)})
|
||||
>>> y = encode({"x": DatetimeMS(-(2**62))})
|
||||
>>> codec_auto = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_AUTO)
|
||||
>>> decode(x, codec_options=codec_auto)
|
||||
{'x': datetime.datetime(1970, 1, 1, 0, 0)}
|
||||
@ -165,7 +162,7 @@ resulting :class:`~datetime.datetime` objects to be within
|
||||
.. doctest::
|
||||
|
||||
>>> x = encode({"x": DatetimeMS(2**62)})
|
||||
>>> y = encode({"x": DatetimeMS(-2**62)})
|
||||
>>> y = encode({"x": DatetimeMS(-(2**62))})
|
||||
>>> codec_clamp = CodecOptions(datetime_conversion=DatetimeConversion.DATETIME_CLAMP)
|
||||
>>> decode(x, codec_options=codec_clamp)
|
||||
{'x': datetime.datetime(9999, 12, 31, 23, 59, 59, 999000)}
|
||||
|
||||
@ -4,8 +4,9 @@ Geospatial Indexing Example
|
||||
.. testsetup::
|
||||
|
||||
from pymongo import MongoClient
|
||||
|
||||
client = MongoClient()
|
||||
client.drop_database('geo_example')
|
||||
client.drop_database("geo_example")
|
||||
|
||||
This example shows how to create and use a :data:`~pymongo.GEO2D`
|
||||
index in PyMongo. To create a spherical (earth-like) geospatial index use :data:`~pymongo.GEOSPHERE` instead.
|
||||
@ -33,10 +34,9 @@ insert a couple of example locations:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> result = db.places.insert_many([{"loc": [2, 5]},
|
||||
... {"loc": [30, 5]},
|
||||
... {"loc": [1, 2]},
|
||||
... {"loc": [4, 4]}])
|
||||
>>> result = db.places.insert_many(
|
||||
... [{"loc": [2, 5]}, {"loc": [30, 5]}, {"loc": [1, 2]}, {"loc": [4, 4]}]
|
||||
... )
|
||||
>>> result.inserted_ids
|
||||
[ObjectId('...'), ObjectId('...'), ObjectId('...'), ObjectId('...')]
|
||||
|
||||
@ -51,7 +51,7 @@ Using the geospatial index we can find documents near another point:
|
||||
|
||||
>>> import pprint
|
||||
>>> for doc in db.places.find({"loc": {"$near": [3, 6]}}).limit(3):
|
||||
... pprint.pprint(doc)
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
{'_id': ObjectId('...'), 'loc': [2, 5]}
|
||||
{'_id': ObjectId('...'), 'loc': [4, 4]}
|
||||
@ -66,7 +66,7 @@ The $maxDistance operator requires the use of :class:`~bson.son.SON`:
|
||||
>>> from bson.son import SON
|
||||
>>> query = {"loc": SON([("$near", [3, 6]), ("$maxDistance", 100)])}
|
||||
>>> for doc in db.places.find(query).limit(3):
|
||||
... pprint.pprint(doc)
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
{'_id': ObjectId('...'), 'loc': [2, 5]}
|
||||
{'_id': ObjectId('...'), 'loc': [4, 4]}
|
||||
@ -78,8 +78,9 @@ It's also possible to query for all items within a given rectangle
|
||||
.. doctest::
|
||||
|
||||
>>> query = {"loc": {"$within": {"$box": [[2, 2], [5, 6]]}}}
|
||||
>>> for doc in db.places.find(query).sort('_id'):
|
||||
>>> for doc in db.places.find(query).sort("_id"):
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
{'_id': ObjectId('...'), 'loc': [2, 5]}
|
||||
{'_id': ObjectId('...'), 'loc': [4, 4]}
|
||||
|
||||
@ -88,8 +89,8 @@ Or circle (specified by center point and radius):
|
||||
.. doctest::
|
||||
|
||||
>>> query = {"loc": {"$within": {"$center": [[0, 0], 6]}}}
|
||||
>>> for doc in db.places.find(query).sort('_id'):
|
||||
... pprint.pprint(doc)
|
||||
>>> for doc in db.places.find(query).sort("_id"):
|
||||
... pprint.pprint(doc)
|
||||
...
|
||||
{'_id': ObjectId('...'), 'loc': [2, 5]}
|
||||
{'_id': ObjectId('...'), 'loc': [1, 2]}
|
||||
|
||||
@ -38,10 +38,12 @@ handler to end background greenlets when your application receives SIGHUP:
|
||||
|
||||
import signal
|
||||
|
||||
|
||||
def graceful_reload(signum, traceback):
|
||||
"""Explicitly close some global MongoClient object."""
|
||||
client.close()
|
||||
|
||||
|
||||
signal.signal(signal.SIGHUP, graceful_reload)
|
||||
|
||||
Applications using uWSGI prior to 1.9.16 are affected by this issue,
|
||||
|
||||
@ -4,8 +4,9 @@ GridFS Example
|
||||
.. testsetup::
|
||||
|
||||
from pymongo import MongoClient
|
||||
|
||||
client = MongoClient()
|
||||
client.drop_database('gridfs_example')
|
||||
client.drop_database("gridfs_example")
|
||||
|
||||
This example shows how to use :mod:`gridfs` to store large binary
|
||||
objects (e.g. files) in MongoDB.
|
||||
|
||||
@ -55,12 +55,12 @@ selector function:
|
||||
|
||||
>>> def server_selector(server_descriptions):
|
||||
... servers = [
|
||||
... server for server in server_descriptions
|
||||
... if server.address[0] == 'localhost'
|
||||
... server for server in server_descriptions if server.address[0] == "localhost"
|
||||
... ]
|
||||
... if not servers:
|
||||
... return server_descriptions
|
||||
... return servers
|
||||
...
|
||||
|
||||
|
||||
|
||||
|
||||
@ -81,7 +81,7 @@ Subclasses of :py:class:`collections.abc.Mapping` can also be used, such as :cla
|
||||
>>> from pymongo import MongoClient
|
||||
>>> client = MongoClient(document_class=SON[str, int])
|
||||
>>> collection = client.test.test
|
||||
>>> inserted = collection.insert_one({"x": 1, "y": 2 })
|
||||
>>> inserted = collection.insert_one({"x": 1, "y": 2})
|
||||
>>> result = collection.find_one({"x": 1})
|
||||
>>> assert result is not None
|
||||
>>> assert result["x"] == 1
|
||||
@ -103,8 +103,8 @@ These methods automatically add an "_id" field.
|
||||
>>> from pymongo import MongoClient
|
||||
>>> from pymongo.collection import Collection
|
||||
>>> class Movie(TypedDict):
|
||||
... name: str
|
||||
... year: int
|
||||
... name: str
|
||||
... year: int
|
||||
...
|
||||
>>> client: MongoClient = MongoClient()
|
||||
>>> collection: Collection[Movie] = client.test.test
|
||||
@ -113,7 +113,7 @@ These methods automatically add an "_id" field.
|
||||
>>> assert result is not None
|
||||
>>> assert result["year"] == 1993
|
||||
>>> # This will raise a type-checking error, despite being present, because it is added by PyMongo.
|
||||
>>> assert result["_id"] # type:ignore[typeddict-item]
|
||||
>>> assert result["_id"] # type:ignore[typeddict-item]
|
||||
|
||||
This same typing scheme works for all of the insert methods (:meth:`~pymongo.collection.Collection.insert_one`,
|
||||
:meth:`~pymongo.collection.Collection.insert_many`, and :meth:`~pymongo.collection.Collection.bulk_write`).
|
||||
@ -158,18 +158,18 @@ Note: to use :py:class:`~typing.TypedDict` and :py:class:`~typing.NotRequired` i
|
||||
>>> from pymongo.collection import Collection
|
||||
>>> from bson import ObjectId
|
||||
>>> class Movie(TypedDict):
|
||||
... name: str
|
||||
... year: int
|
||||
... name: str
|
||||
... year: int
|
||||
...
|
||||
>>> class ExplicitMovie(TypedDict):
|
||||
... _id: ObjectId
|
||||
... name: str
|
||||
... year: int
|
||||
... _id: ObjectId
|
||||
... name: str
|
||||
... year: int
|
||||
...
|
||||
>>> class NotRequiredMovie(TypedDict):
|
||||
... _id: NotRequired[ObjectId]
|
||||
... name: str
|
||||
... year: int
|
||||
... _id: NotRequired[ObjectId]
|
||||
... name: str
|
||||
... year: int
|
||||
...
|
||||
>>> client: MongoClient = MongoClient()
|
||||
>>> collection: Collection[Movie] = client.test.test
|
||||
@ -180,7 +180,9 @@ Note: to use :py:class:`~typing.TypedDict` and :py:class:`~typing.NotRequired` i
|
||||
>>> assert result["_id"] # type:ignore[typeddict-item]
|
||||
>>> collection: Collection[ExplicitMovie] = client.test.test
|
||||
>>> # Note that the _id keyword argument must be supplied
|
||||
>>> inserted = collection.insert_one(ExplicitMovie(_id=ObjectId(), name="Jurassic Park", year=1993))
|
||||
>>> inserted = collection.insert_one(
|
||||
... ExplicitMovie(_id=ObjectId(), name="Jurassic Park", year=1993)
|
||||
... )
|
||||
>>> result = collection.find_one({"name": "Jurassic Park"})
|
||||
>>> assert result is not None
|
||||
>>> # This will not raise a type-checking error.
|
||||
@ -207,13 +209,13 @@ match a well-defined schema using :py:class:`~typing.TypedDict` (Python 3.8+).
|
||||
>>> from pymongo import MongoClient
|
||||
>>> from pymongo.database import Database
|
||||
>>> class Movie(TypedDict):
|
||||
... name: str
|
||||
... year: int
|
||||
... name: str
|
||||
... year: int
|
||||
...
|
||||
>>> client: MongoClient = MongoClient()
|
||||
>>> db: Database[Movie] = client.test
|
||||
>>> collection = db.test
|
||||
>>> inserted = collection.insert_one({"name": "Jurassic Park", "year": 1993 })
|
||||
>>> inserted = collection.insert_one({"name": "Jurassic Park", "year": 1993})
|
||||
>>> result = collection.find_one({"name": "Jurassic Park"})
|
||||
>>> assert result is not None
|
||||
>>> assert result["year"] == 1993
|
||||
@ -244,11 +246,11 @@ You can specify the document type returned by :mod:`bson` decoding functions by
|
||||
>>> from typing import Any, Dict
|
||||
>>> from bson import CodecOptions, encode, decode
|
||||
>>> class MyDict(Dict[str, Any]):
|
||||
... def foo(self):
|
||||
... return "bar"
|
||||
... def foo(self):
|
||||
... return "bar"
|
||||
...
|
||||
>>> options = CodecOptions(document_class=MyDict)
|
||||
>>> doc = {"x": 1, "y": 2 }
|
||||
>>> doc = {"x": 1, "y": 2}
|
||||
>>> bsonbytes = encode(doc, codec_options=options)
|
||||
>>> rt_document = decode(bsonbytes, codec_options=options)
|
||||
>>> assert rt_document.foo() == "bar"
|
||||
|
||||
@ -244,8 +244,7 @@ Key order in subdocuments -- why does my query work in the shell but not PyMongo
|
||||
|
||||
collection = MongoClient().test.collection
|
||||
collection.drop()
|
||||
collection.insert_one({'_id': 1.0,
|
||||
'subdocument': SON([('b', 1.0), ('a', 1.0)])})
|
||||
collection.insert_one({"_id": 1.0, "subdocument": SON([("b", 1.0), ("a", 1.0)])})
|
||||
|
||||
The key-value pairs in a BSON document can have any order (except that ``_id``
|
||||
is always first). The mongo shell preserves key order when reading and writing
|
||||
@ -537,6 +536,7 @@ objects as before:
|
||||
<pymongo.results.InsertOneResult object at 0x...>
|
||||
>>> for x in client.db.collection.find():
|
||||
... print(x)
|
||||
...
|
||||
{'_id': ObjectId('...'), 'x': datetime.datetime(1970, 1, 1, 0, 0)}
|
||||
{'_id': ObjectId('...'), 'x': DatetimeMS(4611686018427387904)}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ PyMongo 4 Migration Guide
|
||||
.. testsetup::
|
||||
|
||||
from pymongo import MongoClient, ReadPreference
|
||||
|
||||
client = MongoClient()
|
||||
database = client.my_database
|
||||
collection = database.my_collection
|
||||
|
||||
@ -4,8 +4,9 @@ Tutorial
|
||||
.. testsetup::
|
||||
|
||||
from pymongo import MongoClient
|
||||
|
||||
client = MongoClient()
|
||||
client.drop_database('test-database')
|
||||
client.drop_database("test-database")
|
||||
|
||||
This tutorial is intended as an introduction to working with
|
||||
**MongoDB** and **PyMongo**.
|
||||
@ -45,13 +46,13 @@ specify the host and port explicitly, as follows:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> client = MongoClient('localhost', 27017)
|
||||
>>> client = MongoClient("localhost", 27017)
|
||||
|
||||
Or use the MongoDB URI format:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> client = MongoClient('mongodb://localhost:27017/')
|
||||
>>> client = MongoClient("mongodb://localhost:27017/")
|
||||
|
||||
Getting a Database
|
||||
------------------
|
||||
@ -70,7 +71,7 @@ instead:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> db = client['test-database']
|
||||
>>> db = client["test-database"]
|
||||
|
||||
Getting a Collection
|
||||
--------------------
|
||||
@ -87,7 +88,7 @@ or (using dictionary style access):
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> collection = db['test-collection']
|
||||
>>> collection = db["test-collection"]
|
||||
|
||||
An important note about collections (and databases) in MongoDB is that
|
||||
they are created lazily - none of the above commands have actually
|
||||
@ -104,10 +105,12 @@ post:
|
||||
.. doctest::
|
||||
|
||||
>>> import datetime
|
||||
>>> post = {"author": "Mike",
|
||||
... "text": "My first blog post!",
|
||||
... "tags": ["mongodb", "python", "pymongo"],
|
||||
... "date": datetime.datetime.utcnow()}
|
||||
>>> post = {
|
||||
... "author": "Mike",
|
||||
... "text": "My first blog post!",
|
||||
... "tags": ["mongodb", "python", "pymongo"],
|
||||
... "date": datetime.datetime.utcnow(),
|
||||
... }
|
||||
|
||||
Note that documents can contain native Python types (like
|
||||
:class:`datetime.datetime` instances) which will be automatically
|
||||
@ -212,7 +215,7 @@ Note that an ObjectId is not the same as its string representation:
|
||||
.. doctest::
|
||||
|
||||
>>> post_id_as_str = str(post_id)
|
||||
>>> posts.find_one({"_id": post_id_as_str}) # No result
|
||||
>>> posts.find_one({"_id": post_id_as_str}) # No result
|
||||
>>>
|
||||
|
||||
A common task in web applications is to get an ObjectId from the
|
||||
@ -240,14 +243,20 @@ command to the server:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> new_posts = [{"author": "Mike",
|
||||
... "text": "Another post!",
|
||||
... "tags": ["bulk", "insert"],
|
||||
... "date": datetime.datetime(2009, 11, 12, 11, 14)},
|
||||
... {"author": "Eliot",
|
||||
... "title": "MongoDB is fun",
|
||||
... "text": "and pretty easy too!",
|
||||
... "date": datetime.datetime(2009, 11, 10, 10, 45)}]
|
||||
>>> new_posts = [
|
||||
... {
|
||||
... "author": "Mike",
|
||||
... "text": "Another post!",
|
||||
... "tags": ["bulk", "insert"],
|
||||
... "date": datetime.datetime(2009, 11, 12, 11, 14),
|
||||
... },
|
||||
... {
|
||||
... "author": "Eliot",
|
||||
... "title": "MongoDB is fun",
|
||||
... "text": "and pretty easy too!",
|
||||
... "date": datetime.datetime(2009, 11, 10, 10, 45),
|
||||
... },
|
||||
... ]
|
||||
>>> result = posts.insert_many(new_posts)
|
||||
>>> result.inserted_ids
|
||||
[ObjectId('...'), ObjectId('...')]
|
||||
@ -274,7 +283,7 @@ document in the ``posts`` collection:
|
||||
.. doctest::
|
||||
|
||||
>>> for post in posts.find():
|
||||
... pprint.pprint(post)
|
||||
... pprint.pprint(post)
|
||||
...
|
||||
{'_id': ObjectId('...'),
|
||||
'author': 'Mike',
|
||||
@ -300,7 +309,7 @@ author is "Mike":
|
||||
.. doctest::
|
||||
|
||||
>>> for post in posts.find({"author": "Mike"}):
|
||||
... pprint.pprint(post)
|
||||
... pprint.pprint(post)
|
||||
...
|
||||
{'_id': ObjectId('...'),
|
||||
'author': 'Mike',
|
||||
@ -343,7 +352,7 @@ than a certain date, but also sort the results by author:
|
||||
|
||||
>>> d = datetime.datetime(2009, 11, 12, 12)
|
||||
>>> for post in posts.find({"date": {"$lt": d}}).sort("author"):
|
||||
... pprint.pprint(post)
|
||||
... pprint.pprint(post)
|
||||
...
|
||||
{'_id': ObjectId('...'),
|
||||
'author': 'Eliot',
|
||||
@ -373,8 +382,7 @@ First, we'll need to create the index:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> result = db.profiles.create_index([('user_id', pymongo.ASCENDING)],
|
||||
... unique=True)
|
||||
>>> result = db.profiles.create_index([("user_id", pymongo.ASCENDING)], unique=True)
|
||||
>>> sorted(list(db.profiles.index_information()))
|
||||
['_id_', 'user_id_1']
|
||||
|
||||
@ -386,9 +394,7 @@ Now let's set up some user profiles:
|
||||
|
||||
.. doctest::
|
||||
|
||||
>>> user_profiles = [
|
||||
... {'user_id': 211, 'name': 'Luke'},
|
||||
... {'user_id': 212, 'name': 'Ziltoid'}]
|
||||
>>> user_profiles = [{"user_id": 211, "name": "Luke"}, {"user_id": 212, "name": "Ziltoid"}]
|
||||
>>> result = db.profiles.insert_many(user_profiles)
|
||||
|
||||
The index prevents us from inserting a document whose ``user_id`` is already in
|
||||
@ -397,8 +403,8 @@ the collection:
|
||||
.. doctest::
|
||||
:options: +IGNORE_EXCEPTION_DETAIL
|
||||
|
||||
>>> new_profile = {'user_id': 213, 'name': 'Drew'}
|
||||
>>> duplicate_profile = {'user_id': 212, 'name': 'Tommy'}
|
||||
>>> new_profile = {"user_id": 213, "name": "Drew"}
|
||||
>>> duplicate_profile = {"user_id": 212, "name": "Tommy"}
|
||||
>>> result = db.profiles.insert_one(new_profile) # This is fine.
|
||||
>>> result = db.profiles.insert_one(duplicate_profile)
|
||||
Traceback (most recent call last):
|
||||
|
||||
@ -23,12 +23,11 @@ Causally Consistent Reads
|
||||
|
||||
with client.start_session(causal_consistency=True) as session:
|
||||
collection = client.db.collection
|
||||
collection.update_one({'_id': 1}, {'$set': {'x': 10}}, session=session)
|
||||
secondary_c = collection.with_options(
|
||||
read_preference=ReadPreference.SECONDARY)
|
||||
collection.update_one({"_id": 1}, {"$set": {"x": 10}}, session=session)
|
||||
secondary_c = collection.with_options(read_preference=ReadPreference.SECONDARY)
|
||||
|
||||
# A secondary read waits for replication of the write.
|
||||
secondary_c.find_one({'_id': 1}, session=session)
|
||||
secondary_c.find_one({"_id": 1}, session=session)
|
||||
|
||||
If `causal_consistency` is True (the default), read operations that use
|
||||
the session are causally after previous read and write operations. Using a
|
||||
@ -57,8 +56,11 @@ operation:
|
||||
with client.start_session() as session:
|
||||
with session.start_transaction():
|
||||
orders.insert_one({"sku": "abc123", "qty": 100}, session=session)
|
||||
inventory.update_one({"sku": "abc123", "qty": {"$gte": 100}},
|
||||
{"$inc": {"qty": -100}}, session=session)
|
||||
inventory.update_one(
|
||||
{"sku": "abc123", "qty": {"$gte": 100}},
|
||||
{"$inc": {"qty": -100}},
|
||||
session=session,
|
||||
)
|
||||
|
||||
Upon normal completion of ``with session.start_transaction()`` block, the
|
||||
transaction automatically calls :meth:`ClientSession.commit_transaction`.
|
||||
|
||||
@ -2533,14 +2533,13 @@ class Collection(common.BaseObject, Generic[_DocumentType]):
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
with db.collection.watch(
|
||||
[{'$match': {'operationType': 'insert'}}]) as stream:
|
||||
with db.collection.watch([{"$match": {"operationType": "insert"}}]) as stream:
|
||||
for insert_change in stream:
|
||||
print(insert_change)
|
||||
except pymongo.errors.PyMongoError:
|
||||
# The ChangeStream encountered an unrecoverable error or the
|
||||
# resume attempt failed to recreate the cursor.
|
||||
logging.error('...')
|
||||
logging.error("...")
|
||||
|
||||
For a precise description of the resume process see the
|
||||
`change streams specification`_.
|
||||
|
||||
@ -591,14 +591,13 @@ class Database(common.BaseObject, Generic[_DocumentType]):
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
with db.watch(
|
||||
[{'$match': {'operationType': 'insert'}}]) as stream:
|
||||
with db.watch([{"$match": {"operationType": "insert"}}]) as stream:
|
||||
for insert_change in stream:
|
||||
print(insert_change)
|
||||
except pymongo.errors.PyMongoError:
|
||||
# The ChangeStream encountered an unrecoverable error or the
|
||||
# resume attempt failed to recreate the cursor.
|
||||
logging.error('...')
|
||||
logging.error("...")
|
||||
|
||||
For a precise description of the resume process see the
|
||||
`change streams specification`_.
|
||||
|
||||
@ -27,7 +27,7 @@ access:
|
||||
>>> c = MongoClient()
|
||||
>>> c.test_database
|
||||
Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test_database')
|
||||
>>> c['test-database']
|
||||
>>> c["test-database"]
|
||||
Database(MongoClient(host=['localhost:27017'], document_class=dict, tz_aware=False, connect=True), 'test-database')
|
||||
"""
|
||||
|
||||
@ -935,14 +935,13 @@ class MongoClient(common.BaseObject, Generic[_DocumentType]):
|
||||
.. code-block:: python
|
||||
|
||||
try:
|
||||
with client.watch(
|
||||
[{'$match': {'operationType': 'insert'}}]) as stream:
|
||||
with client.watch([{"$match": {"operationType": "insert"}}]) as stream:
|
||||
for insert_change in stream:
|
||||
print(insert_change)
|
||||
except pymongo.errors.PyMongoError:
|
||||
# The ChangeStream encountered an unrecoverable error or the
|
||||
# resume attempt failed to recreate the cursor.
|
||||
logging.error('...')
|
||||
logging.error("...")
|
||||
|
||||
For a precise description of the resume process see the
|
||||
`change streams specification`_.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user