Compare commits

...

1 Commits

Author SHA1 Message Date
Stefan Wojcik
3c8e1e5336 clean up the Document._get_collection code 2017-04-30 14:11:03 -04:00

View File

@ -167,44 +167,62 @@ class Document(BaseDocument):
@classmethod @classmethod
def _get_collection(cls): def _get_collection(cls):
"""Returns the collection for the document.""" """Return a PyMongo collection for the document."""
# TODO: use new get_collection() with PyMongo3 ?
if not hasattr(cls, '_collection') or cls._collection is None: if not hasattr(cls, '_collection') or cls._collection is None:
# Get the collection, either capped or regular.
if cls._meta.get('max_size') or cls._meta.get('max_documents'):
cls._collection = cls._get_capped_collection()
else:
db = cls._get_db() db = cls._get_db()
collection_name = cls._get_collection_name() collection_name = cls._get_collection_name()
# Create collection as a capped collection if specified cls._collection = db[collection_name]
if cls._meta.get('max_size') or cls._meta.get('max_documents'):
# Get max document limit and max byte size from meta # Ensure indexes on the collection unless auto_create_index was
# set to False.
if cls._meta.get('auto_create_index', True):
cls.ensure_indexes()
return cls._collection
@classmethod
def _get_capped_collection(cls):
"""Create a new or get an existing capped PyMongo collection."""
db = cls._get_db()
collection_name = cls._get_collection_name()
# Get max document limit and max byte size from meta.
max_size = cls._meta.get('max_size') or 10 * 2 ** 20 # 10MB default max_size = cls._meta.get('max_size') or 10 * 2 ** 20 # 10MB default
max_documents = cls._meta.get('max_documents') max_documents = cls._meta.get('max_documents')
# Round up to next 256 bytes as MongoDB would do it to avoid exception
# MongoDB will automatically raise the size to make it a multiple of
# 256 bytes. We raise it here ourselves to be able to reliably compare
# the options below.
if max_size % 256: if max_size % 256:
max_size = (max_size // 256 + 1) * 256 max_size = (max_size // 256 + 1) * 256
# If the collection already exists and has different options
# (i.e. isn't capped or has different max/size), raise an error.
if collection_name in db.collection_names(): if collection_name in db.collection_names():
cls._collection = db[collection_name] collection = db[collection_name]
# The collection already exists, check if its capped options = collection.options()
# options match the specified capped options if (
options = cls._collection.options() options.get('max') != max_documents or
if options.get('max') != max_documents or \ options.get('size') != max_size
options.get('size') != max_size: ):
msg = (('Cannot create collection "%s" as a capped ' raise InvalidCollectionError(
'collection as it already exists') 'Cannot create collection "{}" as a capped '
% cls._collection) 'collection as it already exists'.format(cls._collection)
raise InvalidCollectionError(msg) )
else:
# Create the collection as a capped collection return collection
# Create a new capped collection.
opts = {'capped': True, 'size': max_size} opts = {'capped': True, 'size': max_size}
if max_documents: if max_documents:
opts['max'] = max_documents opts['max'] = max_documents
cls._collection = db.create_collection(
collection_name, **opts return db.create_collection(collection_name, **opts)
)
else:
cls._collection = db[collection_name]
if cls._meta.get('auto_create_index', True):
cls.ensure_indexes()
return cls._collection
def to_mongo(self, *args, **kwargs): def to_mongo(self, *args, **kwargs):
data = super(Document, self).to_mongo(*args, **kwargs) data = super(Document, self).to_mongo(*args, **kwargs)