Commit 06ee49b9d7dbd5368ac77ed7c8f34b7251ec1692
1 parent
59ebb7fb
Exists in
master
and in
17 other branches
Added block form of scroll
Showing
4 changed files
with
52 additions
and
13 deletions
Show diff stats
CHANGELOG.md
README.md
@@ -1484,12 +1484,20 @@ To retrieve a very large number of results, use the [scroll API](https://www.ela | @@ -1484,12 +1484,20 @@ To retrieve a very large number of results, use the [scroll API](https://www.ela | ||
1484 | ```ruby | 1484 | ```ruby |
1485 | products = Product.search "*", scroll: "1m" | 1485 | products = Product.search "*", scroll: "1m" |
1486 | while products.any? | 1486 | while products.any? |
1487 | - # do something ... | 1487 | + # process batch ... |
1488 | 1488 | ||
1489 | products = products.scroll | 1489 | products = products.scroll |
1490 | end | 1490 | end |
1491 | ``` | 1491 | ``` |
1492 | 1492 | ||
1493 | +On the master branch, you can also do: | ||
1494 | + | ||
1495 | +```ruby | ||
1496 | +Product.search("*", scroll: "1m").scroll do |batch| | ||
1497 | + # process batch ... | ||
1498 | +end | ||
1499 | +``` | ||
1500 | + | ||
1493 | You should call `scroll` on each new set of results, not the original result. | 1501 | You should call `scroll` on each new set of results, not the original result. |
1494 | 1502 | ||
1495 | ## Nested Data | 1503 | ## Nested Data |
lib/searchkick/results.rb
@@ -228,18 +228,35 @@ module Searchkick | @@ -228,18 +228,35 @@ module Searchkick | ||
228 | def scroll | 228 | def scroll |
229 | raise Searchkick::Error, "Pass `scroll` option to the search method for scrolling" unless scroll_id | 229 | raise Searchkick::Error, "Pass `scroll` option to the search method for scrolling" unless scroll_id |
230 | 230 | ||
231 | - params = { | ||
232 | - scroll: options[:scroll], | ||
233 | - scroll_id: scroll_id | ||
234 | - } | ||
235 | - | ||
236 | - begin | ||
237 | - Searchkick::Results.new(@klass, Searchkick.client.scroll(params), @options) | ||
238 | - rescue Elasticsearch::Transport::Transport::Errors::NotFound => e | ||
239 | - if e.class.to_s =~ /NotFound/ && e.message =~ /search_context_missing_exception/i | ||
240 | - raise Searchkick::Error, "Scroll id has expired" | ||
241 | - else | ||
242 | - raise e | 231 | + if block_given? |
232 | + records = self | ||
233 | + while records.any? | ||
234 | + yield records | ||
235 | + records = records.scroll | ||
236 | + end | ||
237 | + | ||
238 | + begin | ||
239 | + # try to clear scroll | ||
240 | + # not required as scroll will expire | ||
241 | + # but there is a cost to open scrolls | ||
242 | + Searchkick.client.clear_scroll(scroll_id: scroll_id) | ||
243 | + rescue Elasticsearch::Transport::Transport::Error | ||
244 | + # okay if it fails | ||
245 | + end | ||
246 | + else | ||
247 | + params = { | ||
248 | + scroll: options[:scroll], | ||
249 | + scroll_id: scroll_id | ||
250 | + } | ||
251 | + | ||
252 | + begin | ||
253 | + Searchkick::Results.new(@klass, Searchkick.client.scroll(params), @options) | ||
254 | + rescue Elasticsearch::Transport::Transport::Errors::NotFound => e | ||
255 | + if e.class.to_s =~ /NotFound/ && e.message =~ /search_context_missing_exception/i | ||
256 | + raise Searchkick::Error, "Scroll id has expired" | ||
257 | + else | ||
258 | + raise e | ||
259 | + end | ||
243 | end | 260 | end |
244 | end | 261 | end |
245 | end | 262 | end |
test/scroll_test.rb
@@ -61,4 +61,14 @@ class ScrollTest < Minitest::Test | @@ -61,4 +61,14 @@ class ScrollTest < Minitest::Test | ||
61 | end | 61 | end |
62 | assert_match /Pass .+ option/, error.message | 62 | assert_match /Pass .+ option/, error.message |
63 | end | 63 | end |
64 | + | ||
65 | + def test_scroll_block | ||
66 | + store_names ["Product A", "Product B", "Product C", "Product D", "Product E", "Product F"] | ||
67 | + batches_count = 0 | ||
68 | + Product.search("*", scroll: "1m", per_page: 2).scroll do |batch| | ||
69 | + assert_equal 2, batch.size | ||
70 | + batches_count += 1 | ||
71 | + end | ||
72 | + assert_equal 3, batches_count | ||
73 | + end | ||
64 | end | 74 | end |