[Zope-Checkins] SVN: Zope/branches/andig-compositeindex/src/Products/ transpose query integration into the catalog

Andreas Gabriel gabriel at hrz.uni-marburg.de
Wed Sep 29 17:23:02 EDT 2010


Log message for revision 117072:
  transpose query integration into the catalog
  

Changed:
  U   Zope/branches/andig-compositeindex/src/Products/PluginIndexes/CompositeIndex/CompositeIndex.py
  U   Zope/branches/andig-compositeindex/src/Products/PluginIndexes/interfaces.py
  U   Zope/branches/andig-compositeindex/src/Products/ZCatalog/Catalog.py

-=-
Modified: Zope/branches/andig-compositeindex/src/Products/PluginIndexes/CompositeIndex/CompositeIndex.py
===================================================================
--- Zope/branches/andig-compositeindex/src/Products/PluginIndexes/CompositeIndex/CompositeIndex.py	2010-09-29 18:56:43 UTC (rev 117071)
+++ Zope/branches/andig-compositeindex/src/Products/PluginIndexes/CompositeIndex/CompositeIndex.py	2010-09-29 21:23:01 UTC (rev 117072)
@@ -25,27 +25,31 @@
 from BTrees.IOBTree import IOBTree
 import BTrees.Length
 
+from zope.interface import implements
+
 from ZODB.POSException import ConflictError
 
+from Products.PluginIndexes.interfaces import ITransposeQuery
 from Products.PluginIndexes.interfaces import IUniqueValueIndex
 from Products.PluginIndexes.KeywordIndex.KeywordIndex import KeywordIndex
 from Products.PluginIndexes.common.util import parseIndexRequest
 
 from util import PermuteKeywordList
 
-from config import PROJECTNAME
 
+
 _marker = []
 
-logger = logging.getLogger(PROJECTNAME)
+logger = logging.getLogger('CompositeIndex')
 
 class CompositeIndex(KeywordIndex):
 
     """Index for composition of simple fields.
        or sequences of items
     """
+    
+    implements(ITransposeQuery)
 
-
     meta_type="CompositeIndex"
 
     manage_options= (
@@ -455,98 +459,80 @@
             kw = self._tindex.get(k,k)
             items.append((kw, v))
         return items
-    
 
-    manage = manage_main = DTMLFile('dtml/manageCompositeIndex', globals())
-    manage_main._setName('manage_main')
-    manage_browse = DTMLFile('dtml/browseIndex', globals())
 
+    def make_query(self, query):
+        """ optimize the query """
+        
+        cquery = query.copy()
 
-manage_addCompositeIndexForm = DTMLFile('dtml/addCompositeIndex', globals())
+        catalog = aq_parent(self)
 
-def manage_addCompositeIndex(self, id, extra=None,
-                REQUEST=None, RESPONSE=None, URL3=None):
-    """Add a composite index"""
-    return self.manage_addIndex(id, 'CompositeIndex', extra=extra, \
-             REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3)
-
-
-
-class compositeSearchArgumentsMap:
-    """ parse a request from the ZPublisher to optimize the query by means
-        of CompositeIndexes
-    """
-
-    keywords = {}
-    
-    def __init__(self, catalog, request):
-        """ indexes -- dict of index objects
-            request -- the request dictionary send from the ZPublisher
-        """
-        
         indexes = catalog.indexes
 
         parent = aq_parent(catalog)
 
-        if parent.hasProperty('unimr.compositeindex') and not parent.getProperty('unimr.compositeindex',True):
-            logger.warn('skip compositeSearchArgumentsMap')
+        if parent.hasProperty('compositeindex') and not parent.getProperty('compositeindex',True):
+            logger.warn('skip make_query')
             return
         
-        cRank=[]
-        for index in indexes.values():
-            if isinstance(index,CompositeIndex):
-                
-                cId = index.id
-                logger.debug('CompositeIndex "%s" found' % cId)
-                # get indexes managed by CompositeIndex
-                cIdxs = index.getComponentIndexNames()
-                cRank.append((cId,cIdxs))
-        
-        # sort from specific to unspecific CompositeIndex
-        cRank.sort(lambda x,y: cmp((len(y[1]),y[1]),(len(x[1]),x[1])))
+        cIdxs = self.getComponentIndexNames()
 
-        for cId, cIdxs in cRank:
-                records=[]
-                for i in cIdxs:
-                    index = indexes.get(i,None)
-                    abort = False
+        records=[]
+        for i in cIdxs:
+            index = indexes.get(i,None)
+            abort = False
                     
-                    if index:
-                        rec = parseIndexRequest(request, index.id, index.query_options)
+            if index:
+                rec = parseIndexRequest(query, index.id, index.query_options)
                         
-                        if not IUniqueValueIndex.providedBy(index):
-                            logger.warn('index %s: not an instance of IUniqueValueIndex' % index.id)
-                            abort = True
+                if not IUniqueValueIndex.providedBy(index):
+                    logger.warn('index %s: not an instance of IUniqueValueIndex' % index.id)
+                    abort = True
 
-                        if abort or rec.keys is None:
-                            continue
+                if abort or rec.keys is None:
+                    continue
                         
-                        records.append((i, rec))
+                records.append((i, rec))
 
                         
-                # transform request only if more than one component of the composite key is applied 
-                if len(records) > 1:
+        # transform request only if more than one component 
+        # of the composite key is applied 
+        if len(records) > 1:
 
-                    query = { cId: { 'query': records } }
+            cquery.update( { cId: { 'query': records }} )
 
-                    logger.debug('composite query build "%s"' % query)
+                    
+            # delete obsolete query attributes from request
+            for i in cIdxs[:len(records)+1]:
+                if cquery.has_key(i):
+                    del cquery[i]
 
+            logger.debug('composite query build "%s"' % cquery)
+            return cquery
+
+        else:
+            logger.debug('only one component was affected, skip composite query build')
+            
                     
-                    # delete obsolete query attributes from request
-                    for i in cIdxs[:len(records)+1]:
-                        
-                        if isinstance(request, dict):
-                            if request.has_key(i):
-                                del request[i]
-                        else:
-                            if request.keywords.has_key(i):
-                                del request.keywords[i]
-                            if isinstance(request.request, dict) and \
-                                   request.request.has_key(i):
-                               
-                                del request.request[i]
+        return query        
+    
 
-                    request.keywords.update(query)        
- 
+    manage = manage_main = DTMLFile('dtml/manageCompositeIndex', globals())
+    manage_main._setName('manage_main')
+    manage_browse = DTMLFile('dtml/browseIndex', globals())
 
 
+manage_addCompositeIndexForm = DTMLFile('dtml/addCompositeIndex', globals())
+
+def manage_addCompositeIndex(self, id, extra=None,
+                REQUEST=None, RESPONSE=None, URL3=None):
+    """Add a composite index"""
+    return self.manage_addIndex(id, 'CompositeIndex', extra=extra, \
+             REQUEST=REQUEST, RESPONSE=RESPONSE, URL1=URL3)
+
+
+    
+
+        
+

Modified: Zope/branches/andig-compositeindex/src/Products/PluginIndexes/interfaces.py
===================================================================
--- Zope/branches/andig-compositeindex/src/Products/PluginIndexes/interfaces.py	2010-09-29 18:56:43 UTC (rev 117071)
+++ Zope/branches/andig-compositeindex/src/Products/PluginIndexes/interfaces.py	2010-09-29 21:23:01 UTC (rev 117072)
@@ -236,3 +236,13 @@
             E.g. {'indexed_attrs' : ('SearchableText', )}.
             The interface does not define any specifc mapping keys.
         """
+
+
+#
+#
+#
+
+class ITransposeQuery(Interface):
+
+    def make_query(query):
+        """ returns optimized query for given index """

Modified: Zope/branches/andig-compositeindex/src/Products/ZCatalog/Catalog.py
===================================================================
--- Zope/branches/andig-compositeindex/src/Products/ZCatalog/Catalog.py	2010-09-29 18:56:43 UTC (rev 117071)
+++ Zope/branches/andig-compositeindex/src/Products/ZCatalog/Catalog.py	2010-09-29 21:23:01 UTC (rev 117072)
@@ -24,6 +24,7 @@
 from Missing import MV
 from Persistence import Persistent
 from Products.PluginIndexes.interfaces import ILimitedResultIndex
+from Products.PluginIndexes.interfaces import ITransposeQuery
 
 import BTrees.Length
 from BTrees.IIBTree import intersection, weightedIntersection, IISet
@@ -438,6 +439,7 @@
     def make_query(self, request):
         # This is a bit of a mess, but the ZCatalog API has traditionally
         # supported passing in query restrictions in almost arbitary ways
+
         real_req = None
         if isinstance(request, dict):
             query = request.copy()
@@ -471,6 +473,13 @@
                 value = real_req.get(iid)
                 if value:
                     query[iid] = value
+
+        indexes = self.indexes.keys()
+        for i in indexes:
+            index = self.getIndex(i)
+            if ITransposeQuery.providedBy(index):
+                query = index.make_query(query)
+
         return query
 
     def _sorted_search_indexes(self, query):



More information about the Zope-Checkins mailing list