[Checkins] SVN: z3c.indexer/trunk/ Support for sorting by indexed values

Dan Korostelev nadako at gmail.com
Tue Dec 30 10:55:53 EST 2008


Log message for revision 94445:
  Support for sorting by indexed values

Changed:
  U   z3c.indexer/trunk/CHANGES.txt
  U   z3c.indexer/trunk/setup.py
  U   z3c.indexer/trunk/src/z3c/indexer/README.txt
  U   z3c.indexer/trunk/src/z3c/indexer/interfaces.py
  U   z3c.indexer/trunk/src/z3c/indexer/search.py

-=-
Modified: z3c.indexer/trunk/CHANGES.txt
===================================================================
--- z3c.indexer/trunk/CHANGES.txt	2008-12-30 12:07:37 UTC (rev 94444)
+++ z3c.indexer/trunk/CHANGES.txt	2008-12-30 15:55:53 UTC (rev 94445)
@@ -2,10 +2,11 @@
 CHANGES
 =======
 
-0.5.2dev (unreleased)
----------------------
+0.6.0 (unreleased)
+------------------
 
-- ...
+- Feature: added support for sorting by indexed values,
+  introduced in zope.index 3.5.0.
 
 
 0.5.1 (2008-12-11)

Modified: z3c.indexer/trunk/setup.py
===================================================================
--- z3c.indexer/trunk/setup.py	2008-12-30 12:07:37 UTC (rev 94444)
+++ z3c.indexer/trunk/setup.py	2008-12-30 15:55:53 UTC (rev 94445)
@@ -23,9 +23,9 @@
 
 setup (
     name='z3c.indexer',
-    version='0.5.2dev',
+    version='0.6.0dev',
     author = "Roger Ineichen and the Zope Community",
-    author_email = "zope3-dev at zope.org",
+    author_email = "zope-dev at zope.org",
     description = "A new way to index objects for Zope3",
     long_description=(
         read('README.txt')
@@ -86,7 +86,7 @@
         'zope.component',
         'zope.deferredimport',
         'zope.event',
-        'zope.index',
+        'zope.index>=3.5.0',
         'zope.interface',
         'zope.lifecycleevent',
         'zope.location',

Modified: z3c.indexer/trunk/src/z3c/indexer/README.txt
===================================================================
--- z3c.indexer/trunk/src/z3c/indexer/README.txt	2008-12-30 12:07:37 UTC (rev 94444)
+++ z3c.indexer/trunk/src/z3c/indexer/README.txt	2008-12-30 15:55:53 UTC (rev 94445)
@@ -984,12 +984,75 @@
   >>> len(resultSet)
   4
 
-This will returnd the same objects as before:
+This will return the same objects as before:
 
   >>> resultSet[-1:]
   [<DemoContent u'Apple House Tower'>]
 
+Also, the ``searchResults`` provides a way to sort objects
+by their indexed values. You can pass the ``sort_index``,
+``reverse`` and ``limit`` arguments.
 
+If ``sort_index`` is not specified, results are reversed/splitted
+by simple python list mechanisms. That doesn't make any sense
+though, as we can't guarantee any order with that.
+
+  >>> allQuery = SearchQuery(appleQuery).Or(houseQuery).Or(towerQuery)
+
+  >>> list(allQuery.searchResults())
+  [<DemoContent u'Apple'>, <DemoContent u'House'>, <DemoContent u'Tower'>,
+   <DemoContent u'Apple House Tower'>]
+
+  >>> list(allQuery.searchResults(reverse=True))
+  [<DemoContent u'Apple House Tower'>, <DemoContent u'Tower'>,
+   <DemoContent u'House'>, <DemoContent u'Apple'>]
+
+  >>> list(allQuery.searchResults(reverse=True, limit=2))
+  [<DemoContent u'Apple House Tower'>, <DemoContent u'Tower'>]
+
+  >>> list(allQuery.searchResults(limit=2))
+  [<DemoContent u'Apple'>, <DemoContent u'House'>]
+  
+However, when ``sort_index`` is specified, results are sorted
+by values, indexed by specified index using its ``sort`` method.
+Limiting and reversing order are also done by index itself, so
+index can do that efficiently. At the time of writing, only
+the FieldIndexes supports sorting.
+
+Let's provide sensible ``field`` value for our content and
+reindex it.
+
+  >>> apple.field = u'3'
+  >>> house.field = u'6'
+  >>> tower.field = u'2'
+  >>> every.field = u'4'
+  >>> index(apple)
+  >>> index(house)
+  >>> index(tower)
+  >>> index(every)
+
+  >>> list(allQuery.searchResults(sort_index='fieldIndex'))
+  [<DemoContent u'Tower'>, <DemoContent u'Apple'>,
+   <DemoContent u'Apple House Tower'>, <DemoContent u'House'>]
+
+  >>> list(allQuery.searchResults(sort_index='fieldIndex', reverse=True))
+  [<DemoContent u'House'>, <DemoContent u'Apple House Tower'>,
+   <DemoContent u'Apple'>, <DemoContent u'Tower'>]
+
+  >>> list(allQuery.searchResults(sort_index='fieldIndex', limit=2))
+  [<DemoContent u'Tower'>, <DemoContent u'Apple'>]
+
+  >>> list(allQuery.searchResults(sort_index='fieldIndex', reverse=True, limit=2))
+  [<DemoContent u'House'>, <DemoContent u'Apple House Tower'>]
+
+The index must provide the ``zope.index.interfaces.IIndexSort``
+interface, otherwise, TypeError is raised.
+
+  >>> allQuery.searchResults(sort_index='textIndex') 
+  Traceback (most recent call last):
+  ...
+  TypeError: Index textIndex does not implement sorting.
+
 Batching
 --------
 

Modified: z3c.indexer/trunk/src/z3c/indexer/interfaces.py
===================================================================
--- z3c.indexer/trunk/src/z3c/indexer/interfaces.py	2008-12-30 12:07:37 UTC (rev 94444)
+++ z3c.indexer/trunk/src/z3c/indexer/interfaces.py	2008-12-30 15:55:53 UTC (rev 94445)
@@ -49,7 +49,7 @@
     def apply():
         """Return iterable search result wrapper."""
 
-    def searchResults(intids=None):
+    def searchResults(intids=None, sort_index=None, reverse=False, limit=None):
         """Retruns an iterable search result objects. Optional the intids 
         utility can be set for use within the ResulSet implementation.
         """

Modified: z3c.indexer/trunk/src/z3c/indexer/search.py
===================================================================
--- z3c.indexer/trunk/src/z3c/indexer/search.py	2008-12-30 12:07:37 UTC (rev 94444)
+++ z3c.indexer/trunk/src/z3c/indexer/search.py	2008-12-30 15:55:53 UTC (rev 94445)
@@ -19,6 +19,7 @@
 import zope.interface
 import zope.component
 from zope.app.intid.interfaces import IIntIds
+from zope.index.interfaces import IIndexSort
 
 from zc.catalog.index import FamilyProperty
 
@@ -103,14 +104,28 @@
     def apply(self):
         return self.results
 
-    def searchResults(self, intids=None, searchResultFactory=None):
+    def searchResults(self, intids=None, searchResultFactory=None,
+                        sort_index=None, reverse=False, limit=None):
         if searchResultFactory is None:
             searchResultFactory = self.searchResultFactory
         results = []
         if len(self.results) > 0:
+            res = self.results
+            if sort_index is not None:
+                idx = zope.component.getUtility(interfaces.IIndex, name=sort_index)
+                if not IIndexSort.providedBy(idx):
+                    raise TypeError('Index %s does not implement sorting.' % sort_index)
+                res = list(idx.sort(res, reverse, limit))
+            else:
+                if reverse or limit:
+                    res = list(res)
+                if reverse:
+                    res.reverse()
+                if limit:
+                    del res[limit:]
             if intids is None:
                 intids = zope.component.getUtility(IIntIds)
-            results = searchResultFactory(self.results, intids)
+            results = searchResultFactory(res, intids)
         return results
 
     def Or(self, query):



More information about the Checkins mailing list