1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
|
"""
Helper functions, constants, and types to aid with PyMongo support.
"""
import pymongo
from bson import binary, json_util
from pymongo.errors import OperationFailure
PYMONGO_VERSION = tuple(pymongo.version_tuple[:2])
# This will be changed to UuidRepresentation.UNSPECIFIED in a future
# (breaking) release.
if PYMONGO_VERSION >= (4,):
LEGACY_JSON_OPTIONS = json_util.LEGACY_JSON_OPTIONS.with_options(
uuid_representation=binary.UuidRepresentation.PYTHON_LEGACY,
)
else:
LEGACY_JSON_OPTIONS = json_util.DEFAULT_JSON_OPTIONS
def count_documents(
collection, filter, skip=None, limit=None, hint=None, collation=None
):
"""Pymongo>3.7 deprecates count in favour of count_documents"""
if limit == 0:
return 0 # Pymongo raises an OperationFailure if called with limit=0
kwargs = {}
if skip is not None:
kwargs["skip"] = skip
if limit is not None:
kwargs["limit"] = limit
if hint not in (-1, None):
kwargs["hint"] = hint
if collation is not None:
kwargs["collation"] = collation
# count_documents appeared in pymongo 3.7
if PYMONGO_VERSION >= (3, 7):
try:
if not filter and set(kwargs) <= {"max_time_ms"}:
# when no filter is provided, estimated_document_count
# is a lot faster as it uses the collection metadata
return collection.estimated_document_count(**kwargs)
else:
return collection.count_documents(filter=filter, **kwargs)
except OperationFailure as err:
if PYMONGO_VERSION >= (4,):
raise
# OperationFailure - accounts for some operators that used to work
# with .count but are no longer working with count_documents (i.e $geoNear, $near, and $nearSphere)
# fallback to deprecated Cursor.count
# Keeping this should be reevaluated the day pymongo removes .count entirely
if (
"$geoNear, $near, and $nearSphere are not allowed in this context"
not in str(err)
and "$where is not allowed in this context" not in str(err)
):
raise
cursor = collection.find(filter)
for option, option_value in kwargs.items():
cursor_method = getattr(cursor, option)
cursor = cursor_method(option_value)
with_limit_and_skip = "skip" in kwargs or "limit" in kwargs
return cursor.count(with_limit_and_skip=with_limit_and_skip)
def list_collection_names(db, include_system_collections=False):
"""Pymongo>3.7 deprecates collection_names in favour of list_collection_names"""
if PYMONGO_VERSION >= (3, 7):
collections = db.list_collection_names()
else:
collections = db.collection_names()
if not include_system_collections:
collections = [c for c in collections if not c.startswith("system.")]
return collections
|