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
133
134
135
136
137
138
139
|
# File 'lib/supernova/solr_criteria.rb', line 133
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
129
130
131
|
# File 'lib/supernova/solr_criteria.rb', line 129
def build_doc_method(method)
merge_search_options :build_doc_method, method
end
|
#build_docs(docs) ⇒ Object
123
124
125
126
127
|
# File 'lib/supernova/solr_criteria.rb', line 123
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
207
208
209
|
# File 'lib/supernova/solr_criteria.rb', line 207
def collection_from_body(body)
collection_from_json(JSON.parse(body))
end
|
#collection_from_json(json) ⇒ Object
211
212
213
214
215
216
217
218
|
# File 'lib/supernova/solr_criteria.rb', line 211
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!!!
142
143
144
145
146
147
148
149
150
151
152
153
154
155
|
# File 'lib/supernova/solr_criteria.rb', line 142
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
51
52
53
54
55
56
57
58
59
|
# File 'lib/supernova/solr_criteria.rb', line 51
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
203
204
205
|
# File 'lib/supernova/solr_criteria.rb', line 203
def execute
collection_from_body(typhoeus_response.body)
end
|
#execute_async(&block) ⇒ Object
220
221
222
223
224
225
226
|
# File 'lib/supernova/solr_criteria.rb', line 220
def execute_async(&block)
request = typhoeus_request
request.on_complete do |response|
block.call(collection_from_body(response.body))
end
hydra.queue(request)
end
|
165
166
167
|
# File 'lib/supernova/solr_criteria.rb', line 165
def format(the_format)
merge_search_options(:wt, the_format)
end
|
#fq_filter_for_key_and_value(key, value) ⇒ Object
105
106
107
108
109
110
111
112
113
|
# File 'lib/supernova/solr_criteria.rb', line 105
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
# File 'lib/supernova/solr_criteria.rb', line 74
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
|
#hashify_facets_from_response(response) ⇒ Object
179
180
181
182
183
184
185
186
|
# File 'lib/supernova/solr_criteria.rb', line 179
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
195
196
197
|
# File 'lib/supernova/solr_criteria.rb', line 195
def hydra
Typhoeus::Hydra.hydra
end
|
#ids ⇒ Object
232
233
234
|
# File 'lib/supernova/solr_criteria.rb', line 232
def ids
only_ids.execute.ids
end
|
#include_facets? ⇒ Boolean
47
48
49
|
# File 'lib/supernova/solr_criteria.rb', line 47
def include_facets?
self.search_options[:facets] || self.search_options[:facet_queries]
end
|
#only_ids ⇒ Object
228
229
230
|
# File 'lib/supernova/solr_criteria.rb', line 228
def only_ids
self_or_clone.except(:select).select("id")
end
|
#reverse_lookup_solr_field(solr_field) ⇒ Object
65
66
67
68
69
70
71
72
|
# File 'lib/supernova/solr_criteria.rb', line 65
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
157
158
159
160
161
162
163
|
# File 'lib/supernova/solr_criteria.rb', line 157
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
169
170
171
172
173
174
175
176
177
|
# File 'lib/supernova/solr_criteria.rb', line 169
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
61
62
63
|
# File 'lib/supernova/solr_criteria.rb', line 61
def solr_field_from_field(field)
Supernova::SolrIndexer.solr_field_for_field_name_and_mapping(field, search_options[:attribute_mapping])
end
|
#to_params ⇒ Object
move this into separate methods (test each separatly)
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
|
# File 'lib/supernova/solr_criteria.rb', line 5
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 self.search_options[:geo_center] && self.search_options[:geo_distance]
solr_options[:pt] = "#{self.search_options[:geo_center][:lat]},#{self.search_options[:geo_center][:lng]}"
solr_options[:d] = self.search_options[:geo_distance].to_f / Supernova::KM_TO_METER
solr_options[:sfield] = solr_field_from_field(:location)
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
199
200
201
|
# File 'lib/supernova/solr_criteria.rb', line 199
def typhoeus_request
Typhoeus::Request.new(Supernova::Solr.select_url, :params => to_params.merge(:wt => "json"), :method => :post)
end
|
#typhoeus_response ⇒ Object
188
189
190
191
192
193
|
# File 'lib/supernova/solr_criteria.rb', line 188
def typhoeus_response
request = typhoeus_request
hydra.queue(request)
hydra.run
request.response
end
|
#value_for_fq_filter(value) ⇒ Object
115
116
117
118
119
120
121
|
# File 'lib/supernova/solr_criteria.rb', line 115
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
97
98
99
100
101
102
103
|
# File 'lib/supernova/solr_criteria.rb', line 97
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
|