Skip to content

Commit 5f86c18

Browse files
Added support for slicing multiple times in Search class
Fixes elastic#799
1 parent cdb14b6 commit 5f86c18

File tree

3 files changed

+29
-10
lines changed

3 files changed

+29
-10
lines changed

elasticsearch_dsl/search_base.py

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -352,20 +352,27 @@ def __getitem__(self, n):
352352
# If negative slicing, abort.
353353
if n.start and n.start < 0 or n.stop and n.stop < 0:
354354
raise ValueError("Search does not support negative slicing.")
355-
# Elasticsearch won't get all results so we default to size: 10 if
356-
# stop not given.
357-
s._extra["from"] = n.start or 0
358-
s._extra["size"] = max(
359-
0, n.stop - (n.start or 0) if n.stop is not None else 10
360-
)
361-
return s
355+
slice_start = n.start
356+
slice_stop = n.stop
362357
else: # This is an index lookup, equivalent to slicing by [n:n+1].
363358
# If negative index, abort.
364359
if n < 0:
365360
raise ValueError("Search does not support negative indexing.")
366-
s._extra["from"] = n
367-
s._extra["size"] = 1
368-
return s
361+
slice_start = n
362+
slice_stop = n + 1
363+
# Elasticsearch won't get all results so we default to size: 10 if
364+
# stop not given.
365+
old_from = s._extra.get("from", 0)
366+
old_to = old_from + s._extra.get(
367+
"size", slice_stop or (slice_start or old_from) + 10
368+
)
369+
new_from = old_from + (slice_start or 0)
370+
new_to = (
371+
min(old_to, old_from + slice_stop) if slice_stop is not None else old_to
372+
)
373+
s._extra["from"] = new_from
374+
s._extra["size"] = max(0, new_to - new_from)
375+
return s
369376

370377
@classmethod
371378
def from_dict(cls, d):

tests/_async/test_search.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,17 @@ def test_slice():
361361
assert {"from": 3, "size": 10} == s[3:].to_dict()
362362
assert {"from": 0, "size": 0} == s[0:0].to_dict()
363363
assert {"from": 20, "size": 0} == s[20:0].to_dict()
364+
assert {"from": 10, "size": 5} == s[10:][:5].to_dict()
365+
assert {"from": 10, "size": 0} == s[:5][10:].to_dict()
366+
assert {"from": 12, "size": 0} == s[:5][10:][2:].to_dict()
367+
assert {"from": 15, "size": 0} == s[10:][:5][5:].to_dict()
364368

365369

366370
def test_index():
367371
s = AsyncSearch()
368372
assert {"from": 3, "size": 1} == s[3].to_dict()
373+
assert {"from": 3, "size": 1} == s[3][0].to_dict()
374+
assert {"from": 8, "size": 0} == s[3][5].to_dict()
369375

370376

371377
def test_search_to_dict():

tests/_sync/test_search.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,11 +361,17 @@ def test_slice():
361361
assert {"from": 3, "size": 10} == s[3:].to_dict()
362362
assert {"from": 0, "size": 0} == s[0:0].to_dict()
363363
assert {"from": 20, "size": 0} == s[20:0].to_dict()
364+
assert {"from": 10, "size": 5} == s[10:][:5].to_dict()
365+
assert {"from": 10, "size": 0} == s[:5][10:].to_dict()
366+
assert {"from": 12, "size": 0} == s[:5][10:][2:].to_dict()
367+
assert {"from": 15, "size": 0} == s[10:][:5][5:].to_dict()
364368

365369

366370
def test_index():
367371
s = Search()
368372
assert {"from": 3, "size": 1} == s[3].to_dict()
373+
assert {"from": 3, "size": 1} == s[3][0].to_dict()
374+
assert {"from": 8, "size": 0} == s[3][5].to_dict()
369375

370376

371377
def test_search_to_dict():

0 commit comments

Comments
 (0)