[Checkins] SVN: z3c.indexer/trunk/ - bugfix: SearchQuery wasn't able to act correct if initialized with query=None

Roger Ineichen roger at projekt01.ch
Sat Aug 2 07:38:21 EDT 2008


Log message for revision 89196:
  - bugfix: SearchQuery wasn't able to act correct if initialized with query=None
    because of an empty result setup. The And() and Not() methods could not act
    correctly with this an empty initilized result.
  
  - bugfix: SearchQuery.And() and Not() didn't return an empty result if previous
    query result was empty. And() method didn't return a empty result if given
    query was empty. The previous result was returned.
  
  - bugfix: performance tests, not query did not show the right timer in catalog
    cell.
  
  - feature: Expose SearchQuery.results property. Ensure that we return always an
    empty result if None is given and allow to override existing results as a
    part of the SearchQuery API.
  
  - Optimized SearchQuery.And() and Not() methods. Skip given query processing 
    if previous result is empty.
  

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

-=-
Modified: z3c.indexer/trunk/CHANGES.txt
===================================================================
--- z3c.indexer/trunk/CHANGES.txt	2008-08-02 11:36:50 UTC (rev 89195)
+++ z3c.indexer/trunk/CHANGES.txt	2008-08-02 11:38:20 UTC (rev 89196)
@@ -2,6 +2,28 @@
 CHANGES
 =======
 
+Version 0.5.1dev (unreleased)
+-----------------------------
+
+- bugfix: SearchQuery wasn't able to act correct if initialized with query=None
+  because of an empty result setup. The And() and Not() methods could not act
+  correctly with this an empty initilized result.
+
+- bugfix: SearchQuery.And() and Not() didn't return an empty result if previous
+  query result was empty. And() method didn't return a empty result if given
+  query was empty. The previous result was returned.
+
+- bugfix: performance tests, not query did not show the right timer in catalog
+  cell.
+
+- feature: Expose SearchQuery.results property. Ensure that we return always an
+  empty result if None is given and allow to override existing results as a
+  part of the SearchQuery API.
+
+- Optimized SearchQuery.And() and Not() methods. Skip given query processing 
+  if previous result is empty.
+
+
 Version 0.5.0 (2008-05-02)
 --------------------------
 

Modified: z3c.indexer/trunk/setup.py
===================================================================
--- z3c.indexer/trunk/setup.py	2008-08-02 11:36:50 UTC (rev 89195)
+++ z3c.indexer/trunk/setup.py	2008-08-02 11:38:20 UTC (rev 89196)
@@ -23,7 +23,7 @@
 
 setup (
     name='z3c.indexer',
-    version='0.5.0',
+    version='0.5.1dev',
     author = "Roger Ineichen and the Zope Community",
     author_email = "zope3-dev at zope.org",
     description = "A new way to index objects for Zope3",

Modified: z3c.indexer/trunk/src/z3c/indexer/interfaces.py
===================================================================
--- z3c.indexer/trunk/src/z3c/indexer/interfaces.py	2008-08-02 11:36:50 UTC (rev 89195)
+++ z3c.indexer/trunk/src/z3c/indexer/interfaces.py	2008-08-02 11:38:20 UTC (rev 89196)
@@ -33,6 +33,8 @@
     def __init__(query=None, family=None):
         """Initialize with none or existing query."""
 
+    results = zope.interface.Attribute("""List of initids.""")
+
     def apply():
         """Return iterable search result wrapper."""
 

Modified: z3c.indexer/trunk/src/z3c/indexer/performance.py
===================================================================
--- z3c.indexer/trunk/src/z3c/indexer/performance.py	2008-08-02 11:36:50 UTC (rev 89195)
+++ z3c.indexer/trunk/src/z3c/indexer/performance.py	2008-08-02 11:38:20 UTC (rev 89196)
@@ -494,7 +494,7 @@
     print "| type    | indexing |   query | not query |  update |  modify |  remove |"
     print " ------------------------------------------------------------------------"
     print "| catalog | % 7.2fs |% 7.2fs |  % 7.2fs |% 7.2fs |% 7.2fs |% 7.2fs |" % (
-        runCatalogIndexingTime, runCatalogQueryTime, runCatalogQueryTime,
+        runCatalogIndexingTime, runCatalogQueryTime, runCatalogNotQueryTime,
         runCatalogUpdateTime, runCatalogModifiedTime,
         runCatalogObjectRemoveTime)
     print " ------------------------------------------------------------------------"

Modified: z3c.indexer/trunk/src/z3c/indexer/search.py
===================================================================
--- z3c.indexer/trunk/src/z3c/indexer/search.py	2008-08-02 11:36:50 UTC (rev 89195)
+++ z3c.indexer/trunk/src/z3c/indexer/search.py	2008-08-02 11:38:20 UTC (rev 89196)
@@ -21,6 +21,8 @@
 import zope.component
 from zope.app.intid.interfaces import IIntIds
 
+from zc.catalog.index import FamilyProperty
+
 from z3c.indexer import interfaces
 
 
@@ -55,31 +57,53 @@
             yield obj
 
 
+# TODO: allow to initialize with query=None and set the first given query as 
+#       the initial one. If we don't do that, And & Or are never return 
+#       something because of the initial empty IF.Set() 
 class SearchQuery(object):
-    """Chainable query processor."""
+    """Chainable query processor.
+    
+    Note: this search query is and acts as a chain. This means if you apply two
+    query with the And method, the result will contain the intersection of both
+    results. If you later add a query ithin the Or method to the chain the 
+    new result will contain items in the result we skipped with the And method
+    before if the new query contains such (previous Not() filtered) items.
+    """
 
     zope.interface.implements(interfaces.ISearchQuery)
 
-    family = BTrees.family32
+    family = FamilyProperty()
+    _results = None
 
     def __init__(self, query=None, family=None):
         """Initialize with none or existing query."""
-        res= None
+        res = None
         if query is not None:
             res = query.apply()
         if family is not None:
             self.family = family
-        if res:
+        if res is not None:
             self.results = self.family.IF.Set(res)
-        else:
-            self.results = self.family.IF.Set()
 
+    @apply
+    def results():
+        """Ensure a empty result if None is given and allows to override 
+           existing results.
+        """
+        def get(self):
+            if self._results is None:
+                return self.family.IF.Set()
+            return self._results
+        def set(self, results):
+            self._results = results
+        return property(get, set)
+
     def apply(self):
         return self.results
 
     def searchResults(self):
         results = []
-        if self.results is not None:
+        if len(self.results) > 0:
             intids = zope.component.getUtility(IIntIds)
             results = ResultSet(self.results, intids)
         return results
@@ -92,18 +116,29 @@
         """
         res = query.apply()
         if res:
-            self.results = self.family.IF.union(self.results, res)
+            if len(self.results) == 0:
+                # setup our first result if query=None was used in __init__
+                self.results = self.family.IF.Set(res)
+            else:
+                self.results = self.family.IF.union(self.results, res)
         return self
 
     def And(self, query):
         """Restrict search results. (intersection)
 
         The result will only contain intids which exist in the existing
-        result and in the result from te given query. (union)
+        result and in the result from the given query.
         """
+        if len(self.results) == 0:
+            # there is no need to do something if previous results is empty
+            return self
+
         res = query.apply()
         if res:
             self.results = self.family.IF.intersection(self.results, res)
+        # if given query is empty, means we have to return a empty result too!
+        else:
+            self.results = self.family.IF.Set()
         return self
 
     def Not(self, query):
@@ -116,6 +151,10 @@
         processed in a chain, results added after this query get added again. 
         So probably you need to call this at the end of the chain.
         """
+        if len(self.results) == 0:
+            # there is no need to do something if previous results is empty
+            return self
+
         res = query.apply()
         if res:
             self.results = self.family.IF.difference(self.results, res)



More information about the Checkins mailing list