Commits

Matt Chaput committed c7e6b89

Added multi-gap and hardend features to range facets.

  • Participants
  • Parent commits 54b57d7
  • Branches flexisort

Comments (0)

Files changed (2)

src/whoosh/sorting.py

 
 
 class RangeFacet(QueryFacet):
-    def __init__(self, fieldname, start, end, gap):
+    def __init__(self, fieldname, start, end, gap, hardend=False):
         self.fieldname = fieldname
         self.start = start
         self.end = end
         self.gap = gap
+        self.hardend = hardend
         self._queries()
     
     def _range_name(self, startval, endval):
     def _queries(self):
         from whoosh import query
         
+        if not self.gap:
+            raise Exception("No gap secified (%r)" % self.gap)
+        if isinstance(self.gap, (list, tuple)):
+            gaps = self.gap
+            gapindex = 0
+        else:
+            gaps = [self.gap]
+            gapindex = -1
+        
         self.querydict = {}
-        gap = self.gap
         cstart = self.start
         while cstart < self.end:
-            cend = min(self.end, cstart + gap)
+            thisgap = gaps[gapindex]
+            if gapindex >= 0:
+                gapindex += 1
+                if gapindex == len(gaps):
+                    gapindex = -1
+            
+            cend = cstart + thisgap
+            if self.hardend:
+                cend = min(self.end, cend)
+            
             rangename = self._range_name(cstart, cend)
             q = query.NumericRange(self.fieldname, cstart, cend, endexcl=True)
             self.querydict[rangename] = q
             
-            cstart += gap
+            cstart += thisgap
     
     def categorizer(self, searcher):
         return QueryFacet(self.querydict).categorizer(searcher)
     
 
 class DateRangeFacet(RangeFacet):
-    def __init__(self, fieldname, startdate, enddate, delta):
+    def __init__(self, fieldname, startdate, enddate, delta, hardend=False):
         self.fieldname = fieldname
         self.start = datetime_to_long(startdate)
         self.end = datetime_to_long(enddate)
-        self.gap = timedelta_to_usecs(delta)
+        self.hardend = hardend
+        if isinstance(delta, (list, tuple)):
+            self.gap = [timedelta_to_usecs(d) for d in delta]
+        else:
+            self.gap = timedelta_to_usecs(delta)
         self._queries()
     
     def _range_name(self, startval, endval):

tests/test_sorting.py

                                          (200, 300): [0], (500, 600): [4],
                                          None: [2]})
 
+def test_range_gaps():
+    schema = fields.Schema(id=fields.STORED, num=fields.NUMERIC)
+    ix = RamStorage().create_index(schema)
+    w = ix.writer()
+    for i in range(10):
+        w.add_document(id=i, num=i)
+    w.commit()
+    
+    with ix.searcher() as s:
+        rf = sorting.RangeFacet("num", 0, 1000, [1,2,3])
+        r = s.search(query.Every(), groupedby={"num": rf})
+        assert_equal(r.groups("num"), {(0, 1): [0],
+                                       (1, 3): [1, 2],
+                                       (3, 6): [3, 4, 5],
+                                       (6, 9): [6, 7, 8],
+                                       (9, 12): [9]})
+
 def test_daterange_facet():
     from datetime import datetime, timedelta