MongoLite
MongoLite copied to clipboard
Please consider using something other than the pymongo save()
save() in pymongo is "brain damaged". Please consider implementing change tracking and using find_and_modify() to update the document.
Rather than just complain about it, here is some sample code which implements change tracking. Its 'almost' drop in (you'll need to implement the key_in_skeleton function)
class Document(dict):
__fields = ['_id','username', 'age']
def key_in_skeleton(self, key):
#implement this properly pls!
return key in self.__fields
def __init__(self, *args, **kwargs):
self.clear_ops()
dict.__init__(self, *args, **kwargs)
def __setitem__(self, key, value):
if self.key_in_skeleton(key):
t = ('$set', key, value)
self.__ops[key] = t
return super(Document, self).__setitem__(key, value)
def inc(self, key, value=1):
t = ('$inc', key, value)
self.__ops[key] = t
def dec(self, key, value=1):
t = ('$inc', key, -abs(value))
self.__ops[key] = t
@property
def operations(self):
change_set_dict = {}
for key in self.__ops:
change = self.__ops[key]
ctype = change[0]
key = change[1]
value = change[2]
temp = change_set_dict.get(ctype)
if not temp:
temp = {}
change_set_dict[ctype] = temp
temp[key] = value
return change_set_dict;
def clear_ops(self):
self.__ops = {}
pass
def save(self, safe=True):
if hasattr(self, 'pre_save'):
self.pre_save()
new = not self.has_key('_id')
print 'new=', new
if new:
if hasattr(self, 'pre_insert'):
self.pre_insert()
else:
if hasattr(self, 'pre_update'):
self.pre_update()
col = self.collection()
ops = self.operations
print ops
if new:
#if this is an insert, generate an ObjectId and continue!
res = col.find_and_modify(query={'_id':ObjectId()}, update=ops, upsert=True, new=True)
self._id = res['_id']
self.update(res)
if hasattr(self, 'post_insert'):
self.post_insert()
else:
res = col.find_and_modify(query={'_id':self._id}, update=ops, upsert=True, new=True)
self.update(res)
if hasattr(self, 'post_update'):
self.pre_update()
self.clear_ops()
if hasattr(self, 'post_save'):
self.post_save()
pass
pass