Class: Supernova::SolrCriteria
Constant Summary
Constants inherited
from Criteria
Criteria::DEFAULT_PER_PAGE, Criteria::FIRST_PAGE
Instance Attribute Summary
Attributes inherited from Criteria
#clazz, #filters, #results, #search_options
Instance Method Summary
collapse
Methods inherited from Criteria
#attribute_mapping, #clone, #conditions, #current_page, #except, #facet_fields, #facet_queries, #for_classes, #group_by, #immutable!, #immutable?, immutable_by_default!, immutable_by_default?, #implement_in_subclass, #initialize, #limit, #merge, #merge_filters, #merge_filters_array, #merge_filters_or_search_options, #merge_search_options, method_missing, #method_missing, mutable_by_default!, #named_scope_class, #named_scope_defined?, #near, #normalize_coordinates, #options, #order, #paginate, #pagination_attribute_when_greater_zero, #per_page, #populate, #populated?, #read_first_attribute, #rows, #search, #select, select, #self_or_clone, #start, #to_a, #to_parameters, #valid_with_filter?, #where, #with, #within, #without
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
in the class Supernova::Criteria
Instance Method Details
#build_doc(hash) ⇒ Object
181
182
183
184
185
186
187
|
# File 'lib/supernova/solr_criteria.rb', line 181
def build_doc(hash)
if hash["type"].respond_to?(:constantize)
Supernova.build_ar_like_record(hash["type"].constantize, convert_doc_attributes(hash), hash)
else
hash
end
end
|
#build_doc_method(method) ⇒ Object
177
178
179
|
# File 'lib/supernova/solr_criteria.rb', line 177
def build_doc_method(method)
merge_search_options :build_doc_method, method
end
|
#build_docs(docs) ⇒ Object
171
172
173
174
175
|
# File 'lib/supernova/solr_criteria.rb', line 171
def build_docs(docs)
docs.map do |hash|
self.search_options[:build_doc_method] ? self.search_options[:build_doc_method].call(hash) : build_doc(hash)
end
end
|
#collection_from_body(body) ⇒ Object
255
256
257
|
# File 'lib/supernova/solr_criteria.rb', line 255
def collection_from_body(body)
collection_from_json(JSON.parse(body))
end
|
#collection_from_json(json) ⇒ Object
259
260
261
262
263
264
265
266
|
# File 'lib/supernova/solr_criteria.rb', line 259
def collection_from_json(json)
collection = Supernova::Collection.new(current_page, per_page == 0 ? 1 : per_page, json["response"]["numFound"])
collection.original_criteria = self.clone
collection.original_response = json
collection.facets = hashify_facets_from_response(json)
collection.replace(build_docs(json["response"]["docs"]))
collection
end
|
#convert_doc_attributes(hash) ⇒ Object
called in build doc, all hashes have strings as keys!!!
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
# File 'lib/supernova/solr_criteria.rb', line 190
def convert_doc_attributes(hash)
converted_hash = hash.inject({}) do |ret, (key, value)|
if key == "id"
ret["id"] = value.to_s.split("/").last
else
ret[reverse_lookup_solr_field(key).to_s] = value
end
ret
end
self.select_fields.each do |select_field|
converted_hash[select_field.to_s] = nil if !converted_hash.has_key?(select_field.to_s)
end
converted_hash
end
|
#convert_search_order(order) ⇒ Object
99
100
101
102
103
104
105
106
107
|
# File 'lib/supernova/solr_criteria.rb', line 99
def convert_search_order(order)
order.split(/\s*,\s*/).map do |chunk|
if chunk.match(/(.*?) (asc|desc)/i)
"#{solr_field_from_field($1)} #{$2}"
else
chunk
end
end.join(",")
end
|
#execute ⇒ Object
251
252
253
|
# File 'lib/supernova/solr_criteria.rb', line 251
def execute
collection_from_body(typhoeus_response.body)
end
|
#execute_async(&block) ⇒ Object
268
269
270
271
272
273
274
|
# File 'lib/supernova/solr_criteria.rb', line 268
def execute_async(&block)
request = typhoeus_request
request.on_complete do |response|
block.call(collection_from_body(response.body))
end
hydra.queue(request)
end
|
213
214
215
|
# File 'lib/supernova/solr_criteria.rb', line 213
def format(the_format)
merge_search_options(:wt, the_format)
end
|
#fq_filter_for_key_and_value(key, value) ⇒ Object
153
154
155
156
157
158
159
160
161
|
# File 'lib/supernova/solr_criteria.rb', line 153
def fq_filter_for_key_and_value(key, value)
if value.nil?
"!#{key}:[* TO *]"
elsif value.is_a?(Range)
"#{key}:[#{value_for_fq_filter(value.first)} TO #{value_for_fq_filter(value.last)}]"
else
"#{key}:#{value_for_fq_filter(value)}"
end
end
|
#fq_from_with(with) ⇒ Object
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
# File 'lib/supernova/solr_criteria.rb', line 122
def fq_from_with(with)
if with.blank?
[]
else
with.map do |with_part|
if with_part.is_a?(Hash)
with_part.map do |key_or_condition, values|
values_from_key_or_condition_and_values(key_or_condition, values).map do |value|
if key_or_condition.respond_to?(:solr_filter_for)
key_or_condition.key = solr_field_from_field(key_or_condition.key)
key_or_condition.solr_filter_for(value)
else
fq_filter_for_key_and_value(solr_field_from_field(key_or_condition), value)
end
end
end
else
with_part
end
end.flatten
end
end
|
#geo_attributes_from_center_distance_in_meters_and_key(center, distance_in_meters, key) ⇒ Object
32
33
34
35
36
37
38
39
40
|
# File 'lib/supernova/solr_criteria.rb', line 32
def geo_attributes_from_center_distance_in_meters_and_key(center, distance_in_meters, key)
if center && distance_in_meters
{
:pt => "#{center.lat},#{center.lng}",
:d => (distance_in_meters.to_f / Supernova::KM_TO_METER),
:sfield => solr_field_from_field(key)
}
end
end
|
#geo_center ⇒ Object
20
21
22
23
24
25
26
|
# File 'lib/supernova/solr_criteria.rb', line 20
def geo_center
if hash = self.search_options[:geo_center]
Supernova::Coordinate.new(hash)
else
geo_center_from_with
end
end
|
#geo_center_from_with ⇒ Object
8
9
10
|
# File 'lib/supernova/solr_criteria.rb', line 8
def geo_center_from_with
geo_circle_from_with.center if geo_circle_from_with
end
|
#geo_circle_from_with ⇒ Object
4
5
6
|
# File 'lib/supernova/solr_criteria.rb', line 4
def geo_circle_from_with
geo_filter_in_with.at(1) if geo_filter_in_with
end
|
#geo_distance_in_meters ⇒ Object
16
17
18
|
# File 'lib/supernova/solr_criteria.rb', line 16
def geo_distance_in_meters
self.search_options[:geo_distance] || geo_distance_in_meters_from_with
end
|
#geo_distance_in_meters_from_with ⇒ Object
12
13
14
|
# File 'lib/supernova/solr_criteria.rb', line 12
def geo_distance_in_meters_from_with
geo_circle_from_with.radius_in_meters if geo_circle_from_with
end
|
#geo_filed_key ⇒ Object
28
29
30
|
# File 'lib/supernova/solr_criteria.rb', line 28
def geo_filed_key
geo_filter_in_with ? geo_filter_in_with.first : :location
end
|
#geo_filter_in_with ⇒ Object
84
85
86
87
88
89
90
91
92
93
|
# File 'lib/supernova/solr_criteria.rb', line 84
def geo_filter_in_with
(search_options[:with] || []).each do |option|
if option.is_a?(Hash)
option.each do |condition, value|
return [condition.key, value] if value.is_a?(Supernova::Circle)
end
end
end
nil
end
|
#hashify_facets_from_response(response) ⇒ Object
227
228
229
230
231
232
233
234
|
# File 'lib/supernova/solr_criteria.rb', line 227
def hashify_facets_from_response(response)
if response["facet_counts"] && response["facet_counts"]["facet_fields"]
response["facet_counts"]["facet_fields"].inject({}) do |hash, (key, values)|
hash[reverse_lookup_solr_field(key)] = Hash[*values]
hash
end
end
end
|
#hydra ⇒ Object
243
244
245
|
# File 'lib/supernova/solr_criteria.rb', line 243
def hydra
Typhoeus::Hydra.hydra
end
|
#ids ⇒ Object
280
281
282
|
# File 'lib/supernova/solr_criteria.rb', line 280
def ids
only_ids.execute.ids
end
|
#include_facets? ⇒ Boolean
95
96
97
|
# File 'lib/supernova/solr_criteria.rb', line 95
def include_facets?
self.search_options[:facets] || self.search_options[:facet_queries]
end
|
#only_ids ⇒ Object
276
277
278
|
# File 'lib/supernova/solr_criteria.rb', line 276
def only_ids
self_or_clone.except(:select).select("id")
end
|
#reverse_lookup_solr_field(solr_field) ⇒ Object
113
114
115
116
117
118
119
120
|
# File 'lib/supernova/solr_criteria.rb', line 113
def reverse_lookup_solr_field(solr_field)
if search_options[:attribute_mapping]
search_options[:attribute_mapping].each do |field, options|
return field if solr_field.to_s == solr_field_from_field(field)
end
end
solr_field
end
|
#select_fields ⇒ Object
205
206
207
208
209
210
211
|
# File 'lib/supernova/solr_criteria.rb', line 205
def select_fields
if self.search_options[:select].present?
self.search_options[:select]
else
self.search_options[:named_scope_class].respond_to?(:select_fields) ? self.search_options[:named_scope_class].select_fields : []
end
end
|
#set_first_responding_attribute(doc, solr_key, value) ⇒ Object
217
218
219
220
221
222
223
224
225
|
# File 'lib/supernova/solr_criteria.rb', line 217
def set_first_responding_attribute(doc, solr_key, value)
[reverse_lookup_solr_field(solr_key), solr_key].each do |key|
meth = :"#{key}="
if doc.respond_to?(meth)
doc.send(meth, value)
return
end
end
end
|
#solr_field_from_field(field) ⇒ Object
#to_params ⇒ Object
move this into separate methods (test each separatly)
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
# File 'lib/supernova/solr_criteria.rb', line 43
def to_params
solr_options = { :fq => [], :q => "*:*" }
solr_options[:wt] = search_options[:wt] if search_options[:wt]
solr_options[:fq] += fq_from_with(self.search_options[:with])
if self.filters[:without]
self.filters[:without].each do |field, values|
solr_options[:fq] += values.map { |value| "!#{solr_field_from_field(field)}:#{value}" }
end
end
solr_options[:sort] = convert_search_order(self.search_options[:order].join(", ")) if self.search_options[:order]
if self.search_options[:search].is_a?(Array)
solr_options[:q] = self.search_options[:search].map { |query| "(#{query})" }.join(" AND ")
end
if geo_options = geo_attributes_from_center_distance_in_meters_and_key(geo_center, geo_distance_in_meters, geo_filed_key)
solr_options.merge!(geo_options)
solr_options[:fq] << "{!geofilt}"
end
if self.search_options[:select]
self.search_options[:select] << "id" if !self.search_options[:select].map(&:to_s).include?("id")
solr_options[:fl] = self.search_options[:select].compact.map { |field| solr_field_from_field(field) }.join(",")
end
solr_options[:fq] << "type:#{self.clazz}" if self.clazz
solr_options[:facet] = true if include_facets?
if self.search_options[:facets]
solr_options["facet.field"] = self.search_options[:facets].compact.map { |field| solr_field_from_field(field) }
end
if self.search_options[:facet_queries]
solr_options["facet.query"] = self.search_options[:facet_queries].values
end
if self.search_options[:pagination] || search_options[:rows] || search_options[:start]
solr_options[:rows] = self.search_options[:rows] || per_page
solr_options[:start] = search_options[:start] || ((current_page - 1) * solr_options[:rows])
end
solr_options
end
|
#typhoeus_request ⇒ Object
247
248
249
|
# File 'lib/supernova/solr_criteria.rb', line 247
def typhoeus_request
Typhoeus::Request.new(Supernova::Solr.select_url, :params => to_params.merge(:wt => "json"), :method => :get)
end
|
#typhoeus_response ⇒ Object
236
237
238
239
240
241
|
# File 'lib/supernova/solr_criteria.rb', line 236
def typhoeus_response
request = typhoeus_request
hydra.queue(request)
hydra.run
request.response
end
|
#value_for_fq_filter(value) ⇒ Object
163
164
165
166
167
168
169
|
# File 'lib/supernova/solr_criteria.rb', line 163
def value_for_fq_filter(value)
if value.is_a?(Date)
Time.utc(value.year, value.month, value.day).iso8601
else
value
end
end
|
#values_from_key_or_condition_and_values(key_or_condition, values) ⇒ Object
145
146
147
148
149
150
151
|
# File 'lib/supernova/solr_criteria.rb', line 145
def values_from_key_or_condition_and_values(key_or_condition, values)
if key_or_condition.is_a?(Supernova::Condition) && values.is_a?(Array) && [:nin, :in].include?(key_or_condition.type)
[values]
else
[values].flatten
end
end
|