[Checkins] SVN: zope.app.catalog/branches/nadako-sorting/ Create a branch for implement sorting/limiting/reversing resultsets

Dan Korostelev nadako at gmail.com
Sat Dec 27 17:06:40 EST 2008


Log message for revision 94395:
  Create a branch for implement sorting/limiting/reversing resultsets

Changed:
  A   zope.app.catalog/branches/nadako-sorting/
  U   zope.app.catalog/branches/nadako-sorting/CHANGES.txt
  U   zope.app.catalog/branches/nadako-sorting/buildout.cfg
  U   zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/README.txt
  U   zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/catalog.py
  U   zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/interfaces.py

-=-

Property changes on: zope.app.catalog/branches/nadako-sorting
___________________________________________________________________
Added: svn:ignore
   + bin
build
dist
lib
develop-eggs
eggs
parts
.installed.cfg

Added: svn:externals
   + zope.index-sorting svn://svn.zope.org/repos/main/zope.index/branches/nadako-sorting


Modified: zope.app.catalog/branches/nadako-sorting/CHANGES.txt
===================================================================
--- zope.app.catalog/trunk/CHANGES.txt	2008-12-27 21:06:10 UTC (rev 94387)
+++ zope.app.catalog/branches/nadako-sorting/CHANGES.txt	2008-12-27 22:06:40 UTC (rev 94395)
@@ -2,9 +2,11 @@
 CHANGES
 =======
 
-3.5.2 (unreleased)
+3.6.0 (unreleased)
 ------------------
 
+- Add support for sorting, reversing and limiting result set,
+  using new zope.index IIndexSort features.
 - Remove testing dependencies from install_requires.
 
 3.5.1 (2007-10-31)

Modified: zope.app.catalog/branches/nadako-sorting/buildout.cfg
===================================================================
--- zope.app.catalog/trunk/buildout.cfg	2008-12-27 21:06:10 UTC (rev 94387)
+++ zope.app.catalog/branches/nadako-sorting/buildout.cfg	2008-12-27 22:06:40 UTC (rev 94395)
@@ -1,5 +1,5 @@
 [buildout]
-develop = .
+develop = . zope.index-sorting
 parts = test
 
 [test]

Modified: zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/README.txt
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/README.txt	2008-12-27 21:06:10 UTC (rev 94387)
+++ zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/README.txt	2008-12-27 22:06:40 UTC (rev 94395)
@@ -22,6 +22,7 @@
     ...     zope.interface.implements(
     ...         zope.index.interfaces.IInjection,
     ...         zope.index.interfaces.IIndexSearch,
+    ...         zope.index.interfaces.IIndexSort,
     ...         )
     ...
     ...     def clear(self):
@@ -53,6 +54,12 @@
     ...         if set is None:
     ...             set = BTrees.IFBTree.IFTreeSet()
     ...         return set
+    ...
+    ...     def sort(self, docids, limit=None, reverse=False):
+    ...         for i, docid in enumerate(sorted(docids, key=self.backward.get, reverse=reverse)):
+    ...             yield docid
+    ...             if limit and i >= (limit - 1):
+    ...                 break
 
 The class implements `IInjection` to allow values to be indexed and
 unindexed and `IIndexSearch` to support searching via the `apply`
@@ -227,6 +234,54 @@
     >>> list(result) == [o4, o5]
     True
 
+The searchResults method also provides a way to sort, limit and reverse
+results.
+
+When not using sorting, limiting and reversing are done by simple slicing
+and list reversing.
+
+    >>> list(cat.searchResults(size=5, _reverse=True)) == [o5, o4]
+    True
+
+    >>> list(cat.searchResults(size=5, _limit=1)) == [o4]
+    True
+
+    >>> list(cat.searchResults(size=5, _limit=1, _reverse=True)) == [o5]
+    True
+
+However, when using sorting by index, the limit and reverse parameters
+are passed to the index ``sort`` method so it can do it efficiently.
+
+Let's index more objects to work with:
+
+    >>> o7 = DiscriminatingPerson(7, 'blue')
+    >>> o8 = DiscriminatingPerson(3, 'blue')
+    >>> o9 = DiscriminatingPerson(14, 'blue')
+    >>> o10 = DiscriminatingPerson(1, 'blue')
+    >>> ids.data.update({7: o7, 8: o8, 9: o9, 10: o10})
+    >>> cat.index_doc(7, o7)
+    >>> cat.index_doc(8, o8)
+    >>> cat.index_doc(9, o9)
+    >>> cat.index_doc(10, o10)
+
+Now we can search all people who like blue, ordered by age:
+
+    >>> results = list(cat.searchResults(color='blue', _sort_index='age'))
+    >>> results == [o3, o10, o8, o7, o6, o9]
+    True
+
+    >>> results = list(cat.searchResults(color='blue', _sort_index='age', _limit=3))
+    >>> results == [o3, o10, o8]
+    True
+
+    >>> results = list(cat.searchResults(color='blue', _sort_index='age', _reverse=True))
+    >>> results == [o9, o6, o7, o8, o10, o3]
+    True
+
+    >>> results = list(cat.searchResults(color='blue', _sort_index='age', _reverse=True, _limit=4))
+    >>> results == [o9, o6, o7, o8]
+    True
+
 The index example we looked at didn't provide document scores.  Simple
 indexes normally don't, but more complex indexes might give results
 scores, according to how closely a document matches a query.  Let's

Modified: zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/catalog.py
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/catalog.py	2008-12-27 21:06:10 UTC (rev 94387)
+++ zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/catalog.py	2008-12-27 22:06:40 UTC (rev 94395)
@@ -134,8 +134,23 @@
         return result
 
     def searchResults(self, **searchterms):
+        sort_index = searchterms.pop('_sort_index', None)
+        limit = searchterms.pop('_limit', None)
+        reverse = searchterms.pop('_reverse', False)
         results = self.apply(searchterms)
         if results is not None:
+            if sort_index is not None:
+                index = self[sort_index]
+                if not zope.index.interfaces.IIndexSort.providedBy(index):
+                    raise ValueError('Index %s does not support sorting.' % sort_index)
+                results = list(index.sort(results, limit=limit, reverse=reverse))
+            else:
+                if reverse or limit:
+                    results = list(results)
+                if reverse:
+                    results.reverse()
+                if limit:
+                    del results[limit:]
             uidutil = component.getUtility(IIntIds)
             results = ResultSet(results, uidutil)
         return results

Modified: zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/interfaces.py
===================================================================
--- zope.app.catalog/trunk/src/zope/app/catalog/interfaces.py	2008-12-27 21:06:10 UTC (rev 94387)
+++ zope.app.catalog/branches/nadako-sorting/src/zope/app/catalog/interfaces.py	2008-12-27 22:06:40 UTC (rev 94395)
@@ -28,9 +28,26 @@
     """Provides Catalog Queries."""
 
     def searchResults(**kw):
-        """Search on the given indexes."""
+        """Search on the given indexes.
+        
+        Keyword arguments dictionary keys
+        are index names and values are queries
+        for these indexes.
+        
+        Keyword arguments has some special names,
+        used by the catalog itself:
+        
+         * _sort_index - The name of index to sort
+           results with. This index must implement
+           zope.index.interfaces.IIndexSort.
+         * _limit - Limit result set by this number,
+           useful when used with sorting.
+         * _reverse - Reverse result set, also
+           useful with sorting.
 
+        """
 
+
 class ICatalogEdit(zope.index.interfaces.IInjection):
     """Allows one to manipulate the Catalog information."""
 



More information about the Checkins mailing list