diff --git a/elasticutils/__init__.py b/elasticutils/__init__.py index 987fa38..597fcb2 100644 --- a/elasticutils/__init__.py +++ b/elasticutils/__init__.py @@ -28,6 +28,7 @@ 'range', 'statistical', 'terms', + 'terms_stats', ] #: Maps ElasticUtils field actions to their Elasticsearch query names. diff --git a/elasticutils/estestcase.py b/elasticutils/estestcase.py index b6ba374..ad42afe 100644 --- a/elasticutils/estestcase.py +++ b/elasticutils/estestcase.py @@ -112,6 +112,19 @@ def create_index(cls, settings=None): body['settings'] = settings cls.get_es().indices.create(index=cls.index_name, body=body) + @classmethod + def put_mapping(cls, mapping): + """Creates an index with specified settings + + Uses ``cls.index_name`` as the index to create. + + :arg settings: Any additional settings to use to create the + index. + + """ + cls.get_es().indices.put_mapping( + index=cls.index_name, doc_type=cls.mapping_type_name, body=mapping) + @classmethod def index_data(cls, documents, id_field='id'): """Indexes specified data diff --git a/elasticutils/tests/test_query.py b/elasticutils/tests/test_query.py index 809735e..9459225 100644 --- a/elasticutils/tests/test_query.py +++ b/elasticutils/tests/test_query.py @@ -1262,6 +1262,52 @@ def test_facet_date_histogram(self): for item in qs.facet_counts()['created1']] eq_(sorted(facet_counts), [2, 3]) + def test_facet_terms_stats(self): + """Test terms stats facet""" + # FacetTest.create_index() + FacetTest.index_data([ + {'id': 1, "term_id":1, 'value': 1}, + {'id': 2, "term_id":1, 'value': 1}, + {'id': 3, "term_id":1, 'value': 1}, + {'id': 4, "term_id":1, 'value': 2}, + {'id': 5, "term_id":2, 'value': 2}, + {'id': 6, "term_id":2, 'value': 3}, + {'id': 7, "term_id":2, 'value': 3}, + {'id': 8, "term_id":2, 'value': 3}, + {'id': 9, "term_id":2, 'value': 4}, + ]) + FacetTest.refresh() + qs = (self.get_s() + .facet_raw(created1={ + 'terms_stats': { + "key_field": "term_id", + "value_field": "value" + } + }) + ) + + data = qs.facet_counts() + first_term = data["created1"]["terms"][0] + second_term = data["created1"]["terms"][1] + eq_(first_term,{ + u"term": 2, + u"count": 5, + u"total_count": 5, + u"min": 2, + u"max": 4, + u"total": 15, + u"mean": 3.0, + }) + eq_(second_term,{ + u"term": 1, + u"count": 4, + u"total_count": 4, + u"min": 1, + u"max": 2, + u"total": 5, + u"mean": 1.25, + }) + def test_facet_statistical(self): """Test statistical facet""" FacetTest.index_data([ @@ -1354,22 +1400,53 @@ def test_query_facet(self): def test_invalid_field_type(self): """Invalid _type should raise InvalidFacetType.""" + a= {'elasticutilsmappingtype': {'properties': {'pin': {'properties': {'location': {'type': 'geo_point'}}}}}} + FacetTest.put_mapping(mapping=a) FacetTest.index_data([ - {'id': 1, 'age': 30}, - {'id': 2, 'age': 40} + {"id":1, + "pin" : { + "location" : { + "lat" : 40.12, + "lon" : -71.34 + } + } + } ]) FacetTest.refresh() - # Note: This uses a terms_stats facet. If we implement handling + # Note: This uses a geo_distance facet. If we implement handling # for that, then we need to pick another facet type to fail on # or do the right thing and mock the test. - # Note: Previously this used histogram and statistical facets, + # Note: Previously this used histogram, statistical and terms_stats facets, # but those were implemented. with self.assertRaises(InvalidFacetType): (self.get_s() - .facet_raw(created1={'terms_stats': {'key_field': 'age', - 'value_field': 'age'}}) + .facet_raw(created1={ + "geo_distance": { + "pin.location": { + "lat": 40, + "lon": -70 + }, + "ranges": [ + { + "to": 10 + }, + { + "from": 10, + "to": 20 + }, + { + "from": 20, + "to": 100 + }, + { + "from": 100 + } + ] + } + }) .facet_counts()) + FacetTest.mapping = {} class HighlightTest(ESTestCase):