Class: Supernova::SolrCriteria

Inherits:
Criteria
  • Object
show all
Defined in:
lib/supernova/solr_criteria.rb

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, #conditions, #current_page, #facet_fields, #for_classes, #group_by, #implement_in_subclass, #initialize, #limit, #merge, #merge_filters, #merge_filters_array, #merge_filters_or_search_options, #merge_search_options, method_missing, #method_missing, #named_scope_class, #named_scope_defined?, #near, #normalize_coordinates, #options, #order, #paginate, #pagination_attribute_when_greater_zero, #per_page, #populate, #populated?, #read_first_attribute, #search, #select, select, #to_a, #to_parameters, #where, #with, #within, #without

Constructor Details

This class inherits a constructor from Supernova::Criteria

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



118
119
120
121
122
123
124
# File 'lib/supernova/solr_criteria.rb', line 118

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



114
115
116
# File 'lib/supernova/solr_criteria.rb', line 114

def build_doc_method(method)
  merge_search_options :build_doc_method, method
end

#build_docs(docs) ⇒ Object



108
109
110
111
112
# File 'lib/supernova/solr_criteria.rb', line 108

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

#convert_doc_attributes(hash) ⇒ Object

called in build doc, all hashes have strings as keys!!!



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/supernova/solr_criteria.rb', line 127

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



42
43
44
45
46
47
48
49
50
# File 'lib/supernova/solr_criteria.rb', line 42

def convert_search_order(order)
  asc_or_desc = nil
  field = solr_field_from_field(order)
  if order.match(/^(.*?) (asc|desc)/i)
    field = solr_field_from_field($1)
    asc_or_desc = $2
  end
  [field, asc_or_desc].compact.join(" ")
end

#executeObject



169
170
171
172
173
174
175
176
# File 'lib/supernova/solr_criteria.rb', line 169

def execute
  response = Supernova::Solr.connection.post("select", :data => to_params)
  collection = Supernova::Collection.new(current_page, per_page, response["response"]["numFound"])
  collection.original_response = response
  collection.facets = hashify_facets_from_response(response)
  collection.replace(build_docs(response["response"]["docs"]))
  collection
end

#fq_filter_for_key_and_value(key, value) ⇒ Object



90
91
92
93
94
95
96
97
98
# File 'lib/supernova/solr_criteria.rb', line 90

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



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/supernova/solr_criteria.rb', line 65

def fq_from_with(with)
  if with.blank?
    []
  else
    with.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.flatten
  end
end

#hashify_facets_from_response(response) ⇒ Object



160
161
162
163
164
165
166
167
# File 'lib/supernova/solr_criteria.rb', line 160

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

#reverse_lookup_solr_field(solr_field) ⇒ Object



56
57
58
59
60
61
62
63
# File 'lib/supernova/solr_criteria.rb', line 56

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_fieldsObject



142
143
144
145
146
147
148
# File 'lib/supernova/solr_criteria.rb', line 142

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



150
151
152
153
154
155
156
157
158
# File 'lib/supernova/solr_criteria.rb', line 150

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



52
53
54
# File 'lib/supernova/solr_criteria.rb', line 52

def solr_field_from_field(field)
  Supernova::SolrIndexer.solr_field_for_field_name_and_mapping(field, search_options[:attribute_mapping])
end

#to_paramsObject

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
# File 'lib/supernova/solr_criteria.rb', line 5

def to_params
  solr_options = { :fq => [], :q => "*:*" }
  solr_options[:fq] += fq_from_with(self.filters[: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]) 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
    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
  
  if self.search_options[:facets]
    solr_options[:facet] = true
    solr_options["facet.field"] = self.search_options[:facets].compact.map { |field| solr_field_from_field(field) }
  end
  
  if self.search_options[:pagination]
    solr_options[:rows] = per_page
    solr_options[:start] = (current_page - 1) * solr_options[:rows]
  end
  solr_options
end

#value_for_fq_filter(value) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/supernova/solr_criteria.rb', line 100

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



82
83
84
85
86
87
88
# File 'lib/supernova/solr_criteria.rb', line 82

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