[Checkins] SVN: hurry.query/trunk/ Allow to sort on a given index, optionally limiting and reversing the ordered resultset. Bump the future version to 1.1 now that we implemeted addtional features.

Jan-Wijbrand Kolman janwijbrand at gmail.com
Wed Jun 9 04:36:49 EDT 2010


Log message for revision 113300:
  Allow to sort on a given index, optionally limiting and reversing the ordered resultset. Bump the future version to 1.1 now that we implemeted addtional features.

Changed:
  U   hurry.query/trunk/CHANGES.txt
  U   hurry.query/trunk/setup.py
  U   hurry.query/trunk/src/hurry/query/query.py
  U   hurry.query/trunk/src/hurry/query/query.txt

-=-
Modified: hurry.query/trunk/CHANGES.txt
===================================================================
--- hurry.query/trunk/CHANGES.txt	2010-06-09 06:52:09 UTC (rev 113299)
+++ hurry.query/trunk/CHANGES.txt	2010-06-09 08:36:49 UTC (rev 113300)
@@ -1,9 +1,17 @@
 CHANGES
 =======
 
-1.0.1 (unreleased)
+1.1.0 (unreleased)
 ------------------
 
+* Allow the searchResults method of a Query to take an additional keyword
+  argument `sort_field` that defines that defines (catalog_name, index_name) to
+  sort on. That index in that catalog should implement IIndexSort.
+
+  In addition to this keyword argument, `limit` and `reverse` keyword arguments
+  can be passed too, that will limit the sorted resultset and/or reverse its
+  order.
+
 * Allow the searchResults method of a Query object to take an additional
   optional context argument. This context will determine which catalog
   the search is performed on.

Modified: hurry.query/trunk/setup.py
===================================================================
--- hurry.query/trunk/setup.py	2010-06-09 06:52:09 UTC (rev 113299)
+++ hurry.query/trunk/setup.py	2010-06-09 08:36:49 UTC (rev 113300)
@@ -25,7 +25,7 @@
 
 setup(
     name="hurry.query",
-    version = '1.0.1dev',
+    version = '1.1.0dev',
     author='Infrae',
     author_email='faassen at startifact.com',
     description="Higher level query system for the zope.catalog",

Modified: hurry.query/trunk/src/hurry/query/query.py
===================================================================
--- hurry.query/trunk/src/hurry/query/query.py	2010-06-09 06:52:09 UTC (rev 113299)
+++ hurry.query/trunk/src/hurry/query/query.py	2010-06-09 08:36:49 UTC (rev 113300)
@@ -26,7 +26,7 @@
 from zope.component import getUtility
 from zope.interface import implements
 from zope.intid.interfaces import IIntIds
-
+from zope.index.interfaces import IIndexSort
 from hurry.query import interfaces
 
 # XXX look into using multiunion for performance?
@@ -34,14 +34,29 @@
 class Query(object):
     implements(interfaces.IQuery)
 
-    def searchResults(self, query, context=None):
+    def searchResults(
+        self, query, context=None, sort_field=None, limit=None, reverse=False):
+
         results = query.apply(context)
-        if results is not None:
-            uidutil = getUtility(IIntIds, '', context)
-            results = ResultSet(results, uidutil)
-        return results
+        if results is None:
+            return
 
+        if sort_field is not None:
+            catalog_name, index_name = sort_field
+            catalog = getUtility(ICatalog, catalog_name, context)
+            index = catalog[index_name]
+            if not IIndexSort.providedBy(index):
+                raise ValueError(
+                    'Index %s in catalog %s does not support '
+                    'sorting.' % (index_name, catalog_name))
+            results = list(index.sort(results, limit=limit, reverse=reverse))
+        # Note: in case no sort_field is provided, the resultset order
+        # is undefined. As such limiting and reverse does not have any
+        # practical meaning.
+        uidutil = getUtility(IIntIds, '', context)
+        return ResultSet(results, uidutil)
 
+
 class Term(object):
 
     def __and__(self, other):

Modified: hurry.query/trunk/src/hurry/query/query.txt
===================================================================
--- hurry.query/trunk/src/hurry/query/query.txt	2010-06-09 06:52:09 UTC (rev 113299)
+++ hurry.query/trunk/src/hurry/query/query.txt	2010-06-09 08:36:49 UTC (rev 113300)
@@ -439,3 +439,79 @@
 
   >>> displayQuery(In(f1, ['A', 'B']), context=site1)
   [1, 2]
+
+Sorting and limiting the resultset
+----------------------------------
+
+It's possible to have the resultset sorted on one of the fields in the query.
+
+  >>> catalog = Catalog()
+  >>> provideUtility(catalog, ICatalog, 'catalog1')
+  >>> catalog['f1'] = FieldIndex('f1', IContent)
+  >>> catalog['f2'] = FieldIndex('f2', IContent)
+  >>> catalog['t'] = TextIndex('t1', IContent)
+
+First let's set up some new data::
+
+  >>> content = [
+  ... Content(1, 'a', 2, t1='Beautiful is better than ugly.'),
+  ... Content(2, 'a', 3, t1='Explicit is better than implicit'),
+  ... Content(3, 'b', 9, t1='Simple is better than complex'),
+  ... Content(4, 'c', 8, t1='Complex is better than complicated'),
+  ... Content(5, 'c', 7, t1='Readability counts'),
+  ... Content(6, 'a', 1, t1='Although practicality beats purity')]
+
+And catalog them now::
+
+  >>> for entry in content:
+  ...     catalog.index_doc(intid.register(entry), entry)
+
+Define a convenience function for quickly displaying a result set without
+performing any sorting here ourselves.
+
+  >>> def displayResult(q, context=None, **kw):
+  ...     query = getUtility(IQuery)
+  ...     r = query.searchResults(q, context, **kw)
+  ...     return [e.id for e in r]
+
+
+Without using sorting in the query itself, the resultset has an undefined
+order. We "manually" sort the results here to have something testable.
+
+  >>> f1 = ('catalog1', 'f1')
+  >>> [r for r in sorted(displayResult(Eq(f1, 'a')))]
+  [1, 2, 6]
+
+Now we sort on the f2 index.
+
+  >>> f1 = ('catalog1', 'f1')
+  >>> displayResult(Eq(f1, 'a'), sort_field=('catalog1', 'f2'))
+  [6, 1, 2]
+
+Reverse the order.
+
+  >>> f1 = ('catalog1', 'f1')
+  >>> displayResult(Eq(f1, 'a'), sort_field=('catalog1', 'f2'), reverse=True)
+  [2, 1, 6]
+
+We can limit the amount of found items.
+
+  >>> f1 = ('catalog1', 'f1')
+  >>> displayResult(Eq(f1, 'a'), sort_field=('catalog1', 'f2'), limit=2)
+  [6, 1]
+
+We can limit the reversed resultset too.
+
+  >>> f1 = ('catalog1', 'f1')
+  >>> displayResult(
+  ...   Eq(f1, 'a'), sort_field=('catalog1', 'f2'), limit=2, reverse=True)
+  [2, 1]
+
+Whenever a field is used for sorting that does not support is, an error is
+raised.
+
+  >>> f1 = ('catalog1', 'f1')
+  >>> displayResult(Eq(f1, 'a'), sort_field=('catalog1', 't'))
+  Traceback (most recent call last):
+  ...
+  ValueError: Index t in catalog catalog1 does not support sorting.



More information about the checkins mailing list