[Checkins] SVN: mongopersist/trunk/ - Implemented several more mapping methods for the Mongo Container, so that
Stephen Richter
cvs-admin at zope.org
Mon Apr 2 14:06:06 UTC 2012
Log message for revision 124881:
- Implemented several more mapping methods for the Mongo Container, so that
all methods getting the full list of items are fast now.
- Bug: When looking for an item by key/name (``find_*()`` methods) , you would
never get the right object back, but the first one found in the
database. This was due to clobbering the search filter with more general
parameters.
Changed:
U mongopersist/trunk/CHANGES.txt
U mongopersist/trunk/src/mongopersist/performance.py
U mongopersist/trunk/src/mongopersist/zope/container.py
U mongopersist/trunk/src/mongopersist/zope/interfaces.py
U mongopersist/trunk/src/mongopersist/zope/tests/test_container.py
-=-
Modified: mongopersist/trunk/CHANGES.txt
===================================================================
--- mongopersist/trunk/CHANGES.txt 2012-04-02 11:27:33 UTC (rev 124880)
+++ mongopersist/trunk/CHANGES.txt 2012-04-02 14:06:02 UTC (rev 124881)
@@ -2,7 +2,7 @@
CHANGES
=======
-0.7.0 (2012-03-??)
+0.7.0 (2012-04-??)
------------------
- Feature: A new ``IConflictHandler`` interface now controls all aspects of
@@ -73,13 +73,16 @@
of object and where the documents do not store the type (i.e. it is
stored in the name map collection).
- - The Zope Container fast load via find() did not work correctly, since
+ - The Mongo Container fast load via find() did not work correctly, since
setstate() did not change the state from ghost to active and thus the
state was loaded again from MongoDB and set on the object. Now we use the
new ``_latest_states`` cache to lookup a document when ``setstate()`` is
called through the proper channels. Now this "fast load" method truly
causes O(1) database lookups.
+ - Implemented several more mapping methods for the Mongo Container, so that
+ all methods getting the full list of items are fast now.
+
- Whenever the Mongo Object Id is used as a hash key, use the hash of the id
instead. The ``__cmp__()`` method of the ``ObjectId`` class is way too
slow.
@@ -98,7 +101,12 @@
lower problems (by the ratio of read over modified objects) due to lack of
full MVCC.
+- Bug: When looking for an item by key/name (``find_*()`` methods) , you would
+ never get the right object back, but the first one found in the
+ database. This was due to clobbering the search filter with more general
+ parameters.
+
0.6.1 (2012-03-28)
------------------
Modified: mongopersist/trunk/src/mongopersist/performance.py
===================================================================
--- mongopersist/trunk/src/mongopersist/performance.py 2012-04-02 11:27:33 UTC (rev 124880)
+++ mongopersist/trunk/src/mongopersist/performance.py 2012-04-02 14:06:02 UTC (rev 124881)
@@ -75,14 +75,22 @@
# Profile slow read
transaction.begin()
t1 = time.time()
- for name in people:
- person = people[name]
- person.name
+ [people[name].name for name in people]
+ #cProfile.runctx(
+ # '[people[name].name for name in people]', globals(), locals())
t2 = time.time()
- cache = dm._object_cache
transaction.commit()
- print 'Slow Read: %.4f secs' % (t2-t1)
+ print 'Slow Read: %.4f secs' % (t2-t1)
+ # Profile fast read (values)
+ transaction.begin()
+ t1 = time.time()
+ [person.name for person in people.values()]
+ #cProfile.runctx(
+ # '[person.name for person in people.find()]', globals(), locals())
+ t2 = time.time()
+ print 'Fast Read (values): %.4f secs' % (t2-t1)
+
# Profile fast read
transaction.begin()
t1 = time.time()
@@ -90,7 +98,7 @@
#cProfile.runctx(
# '[person.name for person in people.find()]', globals(), locals())
t2 = time.time()
- print 'Fast Read: %.4f secs' % (t2-t1)
+ print 'Fast Read (find): %.4f secs' % (t2-t1)
# Profile modification
t1 = time.time()
@@ -103,7 +111,7 @@
#cProfile.runctx(
# 'modify()', globals(), locals())
t2 = time.time()
- print 'Modification: %.4f secs' % (t2-t1)
+ print 'Modification: %.4f secs' % (t2-t1)
if options.delete:
# Profile deletion
@@ -112,7 +120,7 @@
del people[name]
transaction.commit()
t2 = time.time()
- print 'Deletion: %.4f secs' % (t2-t1)
+ print 'Deletion: %.4f secs' % (t2-t1)
parser = optparse.OptionParser()
parser.usage = '%prog [options]'
Modified: mongopersist/trunk/src/mongopersist/zope/container.py
===================================================================
--- mongopersist/trunk/src/mongopersist/zope/container.py 2012-04-02 11:27:33 UTC (rev 124880)
+++ mongopersist/trunk/src/mongopersist/zope/container.py 2012-04-02 14:06:02 UTC (rev 124881)
@@ -149,6 +149,11 @@
filter[self._m_parent_key] = gs(self._m_get_parent_key_value())
return filter
+ def _m_add_items_filter(self, filter):
+ for key, value in self._m_get_items_filter().items():
+ if key not in filter:
+ filter[key] = value
+
def _load_one(self, doc):
# Create a DBRef object and then load the full state of the object.
dbref = pymongo.dbref.DBRef(
@@ -206,17 +211,29 @@
# Send the uncontained event.
contained.uncontained(value, self, key)
+ def __contains__(self, key):
+ return self.raw_find_one(
+ {self._m_mapping_key: key}, fields=()) is not None
+
+ def __iter__(self):
+ result = self.raw_find(
+ {self._m_mapping_key: {'$ne': None}}, fields=(self._m_mapping_key,))
+ for doc in result:
+ yield doc[self._m_mapping_key]
+
def keys(self):
- filter = self._m_get_items_filter()
- filter[self._m_mapping_key] = {'$ne': None}
- coll = self.get_collection()
- return [doc[self._m_mapping_key]
- for doc in coll.find(filter, fields=(self._m_mapping_key,))]
+ return list(self.__iter__())
+ def iteritems(self):
+ result = self.raw_find()
+ for doc in result:
+ obj = self._load_one(doc)
+ yield doc[self._m_mapping_key], obj
+
def raw_find(self, spec=None, *args, **kwargs):
if spec is None:
spec = {}
- spec.update(self._m_get_items_filter())
+ self._m_add_items_filter(spec)
coll = self.get_collection()
return coll.find(spec, *args, **kwargs)
@@ -232,7 +249,7 @@
spec_or_id = {}
if not isinstance(spec_or_id, dict):
spec_or_id = {'_id': spec_or_id}
- spec_or_id.update(self._m_get_items_filter())
+ self._m_add_items_filter(spec_or_id)
coll = self.get_collection()
return coll.find_one(spec_or_id, *args, **kwargs)
Modified: mongopersist/trunk/src/mongopersist/zope/interfaces.py
===================================================================
--- mongopersist/trunk/src/mongopersist/zope/interfaces.py 2012-04-02 11:27:33 UTC (rev 124880)
+++ mongopersist/trunk/src/mongopersist/zope/interfaces.py 2012-04-02 14:06:02 UTC (rev 124881)
@@ -60,6 +60,12 @@
"""Returns a query spec representing a filter that only returns
objects in this container."""
+ def _m_add_items_filter(filter):
+ """Applies the item filter items to the provided filter.
+
+ Keys that are already in the passed in filter are not overwritten.
+ """
+
def get_collection():
"""Get the Python representation of the collection.
Modified: mongopersist/trunk/src/mongopersist/zope/tests/test_container.py
===================================================================
--- mongopersist/trunk/src/mongopersist/zope/tests/test_container.py 2012-04-02 11:27:33 UTC (rev 124880)
+++ mongopersist/trunk/src/mongopersist/zope/tests/test_container.py 2012-04-02 14:06:02 UTC (rev 124881)
@@ -193,6 +193,8 @@
ObjectId('4e7e9d3ae138232d7b000000'),
u'mongopersist_container_test')}]
+ >>> 'stephan' in dm.root['c']
+ True
>>> dm.root['c'].keys()
[u'stephan']
>>> dm.root['c']['stephan'].__parent__
@@ -207,6 +209,9 @@
...
KeyError: 'roy'
+ >>> 'roy' in dm.root['c']
+ False
+
Now remove the item:
>>> del dm.root['c']['stephan']
More information about the checkins
mailing list