Commit 06ee49b9d7dbd5368ac77ed7c8f34b7251ec1692

Authored by Andrew Kane
1 parent 59ebb7fb

Added block form of scroll

  1 +## 4.0.2 [unreleased]
  2 +
  3 +- Added block form of `scroll`
  4 +
1 ## 4.0.1 5 ## 4.0.1
2 6
3 - Added support for scroll API 7 - Added support for scroll API
@@ -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