Skip to content

Instantly share code, notes, and snippets.

@zaru
Last active August 22, 2021 12:58
Show Gist options
  • Save zaru/6923daa1ca71bb471fd9ed67471a7558 to your computer and use it in GitHub Desktop.
Save zaru/6923daa1ca71bb471fd9ed67471a7558 to your computer and use it in GitHub Desktop.
find_each 風味
class Batches
BATCH_SIZE = 2
def initialize
@data = (1..10).to_a
end
def find_each
if block_given?
find_in_batches do |records|
records.each { |record| yield record }
end
else
enum_for(:find_each)
end
end
def find_in_batches
unless block_given?
return to_enum(:find_in_batches)
end
@start = 0
loop do
batch = @data[@start, BATCH_SIZE]
yield batch
@start += BATCH_SIZE
break if batch.size < BATCH_SIZE
end
end
end
# 直接イテレート
Batches.new.find_each do |record|
puts record
end
# Enumerator オブジェクト受け取ってからイテレート
result = Batches.new.find_each
result.each do |record|
puts record
end
# Elasticsearch のページングを find_each 風に扱えるようにする
class CustomerRepository
include Elasticsearch::Persistence::Repository
include Elasticsearch::Persistence::Repository::DSL
def find_each(query:)
find_in_batches(query: query) do |records|
records.each { |record| yield record }
end
end
def find_in_batches(query:)
search_after = {}
loop do
batch = search({
query: query,
size: BATCH_SIZE,
sort: [
{ email: 'asc' }
]
}.merge(search_after))
yield batch
break if batch.size < BATCH_SIZE
search_after = { search_after: [batch.last.email] }
end
end
end
query = { bool: { must: { match: { foo: 'bar' } } } }
CustomerRepository.new.find_each(query: query) do |record|
puts record
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment