Skip to content

Commit 0f234cf

Browse files
committed
Implemented a RangeFacet for FacetedSearch
Closes elastic#199
1 parent 29609c1 commit 0f234cf

File tree

2 files changed

+53
-5
lines changed

2 files changed

+53
-5
lines changed

elasticsearch_dsl/faceted_search.py

+31-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from .utils import AttrDict
99
from .result import Response
1010

11-
__all__ = ['FacetedSearch', 'HistogramFacet', 'TermsFacet', 'DateHistogramFacet']
11+
__all__ = ['FacetedSearch', 'HistogramFacet', 'TermsFacet', 'DateHistogramFacet', 'RangeFacet']
1212

1313
class Facet(object):
1414
"""
@@ -82,13 +82,41 @@ class TermsFacet(Facet):
8282

8383
def add_filter(self, filter_values):
8484
""" Create a terms filter instead of bool containing term filters. """
85-
8685
self.filter_values = filter_values
87-
8886
if filter_values:
8987
return F('terms', **{self._params['field']: filter_values})
9088

9189

90+
class RangeFacet(Facet):
91+
agg_type = 'range'
92+
93+
def _range_to_dict(self, range):
94+
key, range = range
95+
out = {'key': key}
96+
if range[0] is not None:
97+
out['from'] = range[0]
98+
if range[1] is not None:
99+
out['to'] = range[1]
100+
return out
101+
102+
def __init__(self, ranges, **kwargs):
103+
super(RangeFacet, self).__init__(**kwargs)
104+
self._params['ranges'] = list(map(self._range_to_dict, ranges))
105+
self._params['keyed'] = False
106+
self._ranges = dict(ranges)
107+
108+
def get_value_filter(self, filter_value):
109+
f, t = self._ranges[filter_value]
110+
limits = {}
111+
if f is not None:
112+
limits['from'] = f
113+
if t is not None:
114+
limits['to'] = t
115+
116+
return F('range', **{
117+
self._params['field']: limits
118+
})
119+
92120
class HistogramFacet(Facet):
93121
agg_type = 'histogram'
94122

test_elasticsearch_dsl/test_integration/test_faceted_search.py

+22-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from datetime import datetime
22

3-
from elasticsearch_dsl.faceted_search import FacetedSearch, TermsFacet, DateHistogramFacet
3+
from elasticsearch_dsl.faceted_search import FacetedSearch, TermsFacet, DateHistogramFacet, RangeFacet
44

55
class CommitSearch(FacetedSearch):
66
doc_types = ['commits']
@@ -9,6 +9,7 @@ class CommitSearch(FacetedSearch):
99
facets = {
1010
'files': TermsFacet(field='files'),
1111
'frequency': DateHistogramFacet(field='authored_date', interval="day"),
12+
'deletions': RangeFacet(field='stats.deletions', ranges=[('ok', (None, 1)), ('good', (1, 5)), ('better', (5, None))])
1213
}
1314

1415

@@ -51,7 +52,13 @@ def test_empty_search_finds_everything(data_client):
5152
(datetime(2014, 5, 2, 0, 0), 1, False)
5253
] == r.facets.frequency
5354

54-
def test_filters_are_shown_as_selected_and_data_is_filtered(data_client):
55+
assert [
56+
('ok', 19, False),
57+
('good', 14, False),
58+
('better', 19, False)
59+
] == r.facets.deletions
60+
61+
def test_term_filters_are_shown_as_selected_and_data_is_filtered(data_client):
5562
cs = CommitSearch(filters={'files': 'test_elasticsearch_dsl'})
5663

5764
r = cs.execute()
@@ -87,3 +94,16 @@ def test_filters_are_shown_as_selected_and_data_is_filtered(data_client):
8794
(datetime(2014, 5, 1, 0, 0), 1, False),
8895
(datetime(2014, 5, 2, 0, 0), 1, False)
8996
] == r.facets.frequency
97+
98+
assert [
99+
('ok', 12, False),
100+
('good', 10, False),
101+
('better', 13, False)
102+
] == r.facets.deletions
103+
104+
def test_range_filters_are_shown_as_selected_and_data_is_filtered(data_client):
105+
cs = CommitSearch(filters={'deletions': 'better'})
106+
107+
r = cs.execute()
108+
109+
assert 19 == r.hits.total

0 commit comments

Comments
 (0)