Class: Trample::Search
Class Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#read_attribute_for_serialization
Class Attribute Details
._aggs ⇒ Object
Returns the value of attribute _aggs.
13
14
15
|
# File 'lib/trample/search.rb', line 13
def _aggs
@_aggs
end
|
._conditions ⇒ Object
Returns the value of attribute _conditions.
13
14
15
|
# File 'lib/trample/search.rb', line 13
def _conditions
@_conditions
end
|
._models ⇒ Object
Returns the value of attribute _models.
14
15
16
|
# File 'lib/trample/search.rb', line 14
def _models
@_models
end
|
Class Method Details
.aggregation(name, attrs = {}) {|| ... } ⇒ Object
31
32
33
34
35
36
|
# File 'lib/trample/search.rb', line 31
def self.aggregation(name, attrs = {})
attrs.merge!(name: name)
attrs[:order] = @_aggs.keys.length
@_aggs[name] = Aggregation.new(attrs)
yield @_aggs[name] if block_given?
end
|
.condition(name, attrs = {}) ⇒ Object
25
26
27
28
29
|
# File 'lib/trample/search.rb', line 25
def self.condition(name, attrs = {})
attrs.merge!(name: name, search_klass: self)
@_conditions[name] = Condition.new(attrs)
end
|
.inherited(klass) ⇒ Object
19
20
21
22
23
|
# File 'lib/trample/search.rb', line 19
def self.inherited(klass)
super
klass._conditions = self._conditions.dup
klass._aggs = self._aggs.dup
end
|
.model(*klasses) ⇒ Object
38
39
40
|
# File 'lib/trample/search.rb', line 38
def self.model(*klasses)
@_models = klasses
end
|
.paginate(page_params) ⇒ Object
42
43
44
45
|
# File 'lib/trample/search.rb', line 42
def self.paginate(page_params)
instance = new
instance.paginate(page_params)
end
|
Instance Method Details
#agg(*names_or_payloads) ⇒ Object
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
|
# File 'lib/trample/search.rb', line 78
def agg(*names_or_payloads)
names_or_payloads.each do |name_or_payload|
name = name_or_payload
selections = []
if name_or_payload.is_a?(Hash)
name = name_or_payload.keys.first if name_or_payload.is_a?(Hash)
selections = Array(name_or_payload.values.first)
end
template = self.class._aggs[name.to_sym]
raise AggregationNotDefinedError.new(self, name) unless template
agg = self.aggregations.find { |a| a.name.to_sym == name.to_sym }
if agg.nil?
agg = Aggregation.new(deep_dup(template.attributes).merge(name: name.to_sym))
agg.bucket_sort = template.bucket_sort
self.aggregations << agg
end
selections.each do |key|
bucket = agg.find_or_initialize_bucket(key)
bucket.selected = true
end
end
self
end
|
#aggregations ⇒ Object
121
122
123
124
|
# File 'lib/trample/search.rb', line 121
def aggregations
@aggregations.sort! { |a, b| a.order <=> b.order }
@aggregations
end
|
#aggregations=(aggregation_array) ⇒ Object
N.B rails may send nil here instead of empty array
107
108
109
110
111
112
113
114
115
116
117
118
119
|
# File 'lib/trample/search.rb', line 107
def aggregations=(aggregation_array)
aggregation_array ||= []
super([])
aggregation_array.each do |aggregation_hash|
if aggregation_hash[:buckets] selections = aggregation_hash[:buckets].select { |b| !!b[:selected] }.map { |b| b[:key] }
agg(aggregation_hash[:name].to_sym => selections)
else
agg(aggregation_hash[:name].to_sym => [])
end
end
end
|
#backend ⇒ Object
133
134
135
|
# File 'lib/trample/search.rb', line 133
def backend
@backend ||= Backend::Searchkick.new(metadata, self.class._models)
end
|
#condition(name) ⇒ Object
69
70
71
|
# File 'lib/trample/search.rb', line 69
def condition(name)
ConditionProxy.new(name, self)
end
|
#conditions=(hash) ⇒ Object
126
127
128
129
130
131
|
# File 'lib/trample/search.rb', line 126
def conditions=(hash)
super({})
hash.each_pair do |name, value|
condition(name).set(value)
end
end
|
#find_in_batches(batch_size: 10_000) ⇒ Object
Uses elasticsearch scroll, as ES will blow up > 10_000 results, even if you are paginating.
-
Execute a search, telling ES we are scrolling
-
metadata.scroll_id is set on response
-
Use the scroll_id to fetch the next resultset
-
Repeat until results are exhausted
181
182
183
184
185
186
187
188
189
190
|
# File 'lib/trample/search.rb', line 181
def find_in_batches(batch_size: 10_000)
metadata.scroll = true
metadata..per_page = batch_size
query!
while !self.results.empty?
yield self.results
query!
end
self.metadata = Metadata.new
end
|
#includes(includes) ⇒ Object
73
74
75
|
# File 'lib/trample/search.rb', line 73
def includes(includes)
self.metadata.records[:includes] = includes
end
|
#paginate(page_params) ⇒ Object
47
48
49
50
51
52
|
# File 'lib/trample/search.rb', line 47
def paginate(page_params)
page_params ||= {}
metadata..current_page = page_params[:number] if page_params[:number]
metadata..per_page = page_params[:size] if page_params[:size]
self
end
|
#query!(options = { lookup: true }) ⇒ Object
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
# File 'lib/trample/search.rb', line 137
def query!(options = { lookup: true })
@records = nil
hash = backend.query!(conditions, aggregations)
load_autocompletes if options[:lookup]
self.metadata.took = hash[:took]
self.metadata.scroll_id = hash[:scroll_id]
self.metadata..total = hash[:total]
self.results = hash[:results]
if !!metadata.records[:load]
records!
else
self.results
end
end
|
#records ⇒ Object
Todo only works for single-model search atm N.B. preserves sorting
156
157
158
159
160
161
162
163
164
165
166
167
|
# File 'lib/trample/search.rb', line 156
def records
@records ||= begin
queried = self.class._models.first.where(id: results.map(&:_id))
queried = queried.includes(metadata.records[:includes])
[].tap do |sorted|
results.each do |result|
model = queried.find { |m| m.id.to_s == result.id.to_s }
sorted << model
end
end
end
end
|
#records! ⇒ Object
169
170
171
172
|
# File 'lib/trample/search.rb', line 169
def records!
@records = nil
records
end
|
#sort(*fields) ⇒ Object
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
# File 'lib/trample/search.rb', line 54
def sort(*fields)
return self if fields.empty?
sorts = fields.map do |f|
if f.to_s.starts_with?('-')
f.sub!('-','')
{att: f, dir: :desc}
else
{att: f, dir: :asc}
end
end
self.metadata.sort = sorts
self
end
|