forked from toptal/chewy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
loader.rb
61 lines (54 loc) · 2.17 KB
/
loader.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
module Chewy
module Search
# This class is used for two different purposes: load ORM/ODM
# source objects.
#
# @see Chewy::Index::Import
# @see Chewy::Search::Request#load
# @see Chewy::Search::Response#objects
# @see Chewy::Search::Scrolling#scroll_objects
class Loader
# @param indexes [Array<Chewy::Index>] list of indexes to lookup
# @param options [Hash] adapter-specific load options
# @see Chewy::Index::Adapter::Base#load
def initialize(indexes: [], **options)
@indexes = indexes
@options = options
end
def derive_index(index_name)
index = (@derive_index ||= {})[index_name] ||= indexes_hash[index_name] ||
indexes_hash[indexes_hash.keys.sort_by(&:length)
.reverse.detect do |name|
index_name.match(/#{name}(_.+|\z)/)
end]
raise Chewy::UndefinedIndex, "Can not find index named `#{index}`" unless index
index
end
# For each passed hit this method loads an ORM/ORD source object
# using `hit['_id']`. The returned array is exactly in the same order
# as hits were. If source object was not found for some hit, `nil`
# will be returned at the corresponding position in array.
#
# Records/documents are loaded in an efficient manner, performing
# a single query for each index present.
#
# @param hits [Array<Hash>] ES hits array
# @return [Array<Object, nil>] the array of corresponding ORM/ODM objects
def load(hits)
hit_groups = hits.group_by { |hit| hit['_index'] }
loaded_objects = hit_groups.each_with_object({}) do |(index_name, hit_group), result|
index = derive_index(index_name)
ids = hit_group.map { |hit| hit['_id'] }
loaded = index.adapter.load(ids, **@options.merge(_index: index.base_name))
loaded ||= hit_group.map { |hit| index.build(hit) }
result.merge!(hit_group.zip(loaded).to_h)
end
hits.map { |hit| loaded_objects[hit] }
end
private
def indexes_hash
@indexes_hash ||= @indexes.index_by(&:index_name)
end
end
end
end