Skip to content

Commit 3985719

Browse files
committed
fix: graceful handling of empty __in= lists on ElasticSearch
Thanks to @boulderdave for the ES version of django-haystack#1311 Closes django-haystack#1335
1 parent 10bcc76 commit 3985719

File tree

4 files changed

+38
-5
lines changed

4 files changed

+38
-5
lines changed

docs/changelog.rst

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ Changes
2727
Closes #358
2828
Closes #1311
2929

30+
Fix
31+
~~~
32+
33+
- Graceful handling of empty __in= lists on ElasticSearch. [Chris Adams]
34+
35+
Thanks to @boulderdave for the ES version of #1311
36+
37+
Closes #1335
38+
3039
Other
3140
~~~~~
3241

@@ -2162,8 +2171,9 @@ v2.0.0 (2013-05-12)
21622171
- Fixed an ES test that seems like a change in behavior in recent ES
21632172
versions. [Jannis Leidel]
21642173

2165-
- Merge branch 'sq-run-refactor' of https://github.com/mattdeboard
2166-
/django-haystack into mattdeboard-sq-run-refactor. [Jannis Leidel]
2174+
- Merge branch 'sq-run-refactor' of
2175+
https://github.com/mattdeboard/django-haystack into mattdeboard-sq-
2176+
run-refactor. [Jannis Leidel]
21672177

21682178
- Refactor Solr & ES SearchQuery subclasses to use the ``build_params``
21692179
from ``BaseSearchQuery`` to build the kwargs to be passed to the

haystack/backends/elasticsearch_backend.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -815,10 +815,13 @@ def build_query_fragment(self, field, filter_type, value):
815815
elif filter_type == 'in':
816816
in_options = []
817817

818-
for possible_value in prepared_value:
819-
in_options.append(u'"%s"' % self.backend._from_python(possible_value))
818+
if not prepared_value:
819+
query_frag = u'(!*:*)'
820+
else:
821+
for possible_value in prepared_value:
822+
in_options.append(u'"%s"' % self.backend._from_python(possible_value))
823+
query_frag = u"(%s)" % " OR ".join(in_options)
820824

821-
query_frag = u"(%s)" % " OR ".join(in_options)
822825
elif filter_type == 'range':
823826
start = self.backend._from_python(prepared_value[0])
824827
end = self.backend._from_python(prepared_value[1])

test_haystack/elasticsearch_tests/test_elasticsearch_backend.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,17 @@ def test_auto_query(self):
839839
self.assertEqual(sqs.query.build_query(), u'("pants\\:rule")')
840840
self.assertEqual(len(sqs), 0)
841841

842+
def test_query__in(self):
843+
self.assertGreater(len(self.sqs), 0)
844+
sqs = self.sqs.filter(django_ct='core.mockmodel', django_id__in=[1, 2])
845+
self.assertEqual(len(sqs), 2)
846+
847+
def test_query__in_empty_list(self):
848+
"""Confirm that an empty list avoids a Elasticsearch exception"""
849+
self.assertGreater(len(self.sqs), 0)
850+
sqs = self.sqs.filter(id__in=[])
851+
self.assertEqual(len(sqs), 0)
852+
842853
# Regressions
843854

844855
def test_regression_proper_start_offsets(self):

test_haystack/elasticsearch_tests/test_elasticsearch_query.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,15 @@ def test_narrow_sq(self):
162162
self.assertEqual(len(sqs.query.narrow_queries), 1)
163163
self.assertEqual(sqs.query.narrow_queries.pop(), 'foo:(moof)')
164164

165+
def test_query__in(self):
166+
sqs = SearchQuerySet(using='elasticsearch').filter(id__in=[1, 2, 3])
167+
self.assertEqual(sqs.query.build_query(), u'id:("1" OR "2" OR "3")')
168+
169+
def test_query__in_empty_list(self):
170+
"""Confirm that an empty list avoids a Elasticsearch exception"""
171+
sqs = SearchQuerySet(using='elasticsearch').filter(id__in=[])
172+
self.assertEqual(sqs.query.build_query(), u'id:(!*:*)')
173+
165174

166175
class ElasticsearchSearchQuerySpatialBeforeReleaseTestCase(TestCase):
167176
def setUp(self):

0 commit comments

Comments
 (0)