Added Sharding support
Added shard_key meta, so save() and update() passes shard keys to the pymongo query. Also made shard key fields immutable. Closes #388 and #389
This commit is contained in:
@@ -724,6 +724,7 @@ class TopLevelDocumentMetaclass(DocumentMetaclass):
|
||||
class BaseDocument(object):
|
||||
|
||||
_dynamic = False
|
||||
_created = True
|
||||
|
||||
def __init__(self, **values):
|
||||
signals.pre_init.send(self.__class__, document=self, values=values)
|
||||
@@ -757,6 +758,7 @@ class BaseDocument(object):
|
||||
if self._dynamic:
|
||||
for key, value in dynamic_data.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
signals.post_init.send(self.__class__, document=self)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
@@ -784,6 +786,11 @@ class BaseDocument(object):
|
||||
if hasattr(self, '_changed_fields'):
|
||||
self._mark_as_changed(name)
|
||||
return
|
||||
|
||||
if not self._created and name in self._meta.get('shard_key', tuple()):
|
||||
from queryset import OperationError
|
||||
raise OperationError("Shard Keys are immutable. Tried to update %s" % name)
|
||||
|
||||
super(BaseDocument, self).__setattr__(name, value)
|
||||
|
||||
def __expand_dynamic_values(self, name, value):
|
||||
@@ -912,6 +919,7 @@ class BaseDocument(object):
|
||||
|
||||
obj = cls(**data)
|
||||
obj._changed_fields = changed_fields
|
||||
obj._created = False
|
||||
return obj
|
||||
|
||||
def _mark_as_changed(self, key):
|
||||
|
||||
@@ -171,6 +171,7 @@ class Document(BaseDocument):
|
||||
doc = self.to_mongo()
|
||||
|
||||
created = force_insert or '_id' not in doc
|
||||
|
||||
try:
|
||||
collection = self.__class__.objects._collection
|
||||
if created:
|
||||
@@ -181,10 +182,18 @@ class Document(BaseDocument):
|
||||
else:
|
||||
object_id = doc['_id']
|
||||
updates, removals = self._delta()
|
||||
|
||||
# Need to add shard key to query, or you get an error
|
||||
select_dict = {'_id': object_id}
|
||||
shard_key = self.__class__._meta.get('shard_key', tuple())
|
||||
for k in shard_key:
|
||||
actual_key = self._db_field_map.get(k, k)
|
||||
select_dict[actual_key] = doc[actual_key]
|
||||
|
||||
if updates:
|
||||
collection.update({'_id': object_id}, {"$set": updates}, upsert=True, safe=safe, **write_options)
|
||||
collection.update(select_dict, {"$set": updates}, upsert=True, safe=safe, **write_options)
|
||||
if removals:
|
||||
collection.update({'_id': object_id}, {"$unset": removals}, upsert=True, safe=safe, **write_options)
|
||||
collection.update(select_dict, {"$unset": removals}, upsert=True, safe=safe, **write_options)
|
||||
|
||||
cascade = self._meta.get('cascade', True) if cascade is None else cascade
|
||||
if cascade:
|
||||
@@ -238,7 +247,12 @@ class Document(BaseDocument):
|
||||
if not self.pk:
|
||||
raise OperationError('attempt to update a document not yet saved')
|
||||
|
||||
return self.__class__.objects(pk=self.pk).update_one(**kwargs)
|
||||
# Need to add shard key to query, or you get an error
|
||||
select_dict = {'pk': self.pk}
|
||||
shard_key = self.__class__._meta.get('shard_key', tuple())
|
||||
for k in shard_key:
|
||||
select_dict[k] = getattr(self, k)
|
||||
return self.__class__.objects(**select_dict).update_one(**kwargs)
|
||||
|
||||
def delete(self, safe=False):
|
||||
"""Delete the :class:`~mongoengine.Document` from the database. This
|
||||
@@ -248,10 +262,8 @@ class Document(BaseDocument):
|
||||
"""
|
||||
signals.pre_delete.send(self.__class__, document=self)
|
||||
|
||||
id_field = self._meta['id_field']
|
||||
object_id = self._fields[id_field].to_mongo(self[id_field])
|
||||
try:
|
||||
self.__class__.objects(**{id_field: object_id}).delete(safe=safe)
|
||||
self.__class__.objects(pk=self.pk).delete(safe=safe)
|
||||
except pymongo.errors.OperationFailure, err:
|
||||
message = u'Could not delete document (%s)' % err.message
|
||||
raise OperationError(message)
|
||||
|
||||
Reference in New Issue
Block a user