Skip to content
This repository
Newer
Older
100644 120 lines (106 sloc) 5.268 kb
be5b95d9 » Thiago Jackiw
2008-05-03 git import of acts_as_solr
1 module ActsAsSolr #:nodoc:
2 module ParserMethods
3 protected
4
5 # Method used by mostly all the ClassMethods when doing a search
6 def parse_query(query=nil, options={}, models=nil)
7 valid_options = [:offset, :limit, :facets, :models, :results_format, :order, :scores, :operator]
8 query_options = {}
9 return if query.nil?
10 raise "Invalid parameters: #{(options.keys - valid_options).join(',')}" unless (options.keys - valid_options).empty?
11 begin
12 Deprecation.validate_query(options)
13 query_options[:start] = options[:offset]
14 query_options[:rows] = options[:limit]
15 query_options[:operator] = options[:operator]
16
17 # first steps on the facet parameter processing
18 if options[:facets]
19 query_options[:facets] = {}
20 query_options[:facets][:limit] = -1 # TODO: make this configurable
21 query_options[:facets][:sort] = :count if options[:facets][:sort]
22 query_options[:facets][:mincount] = 0
23 query_options[:facets][:mincount] = 1 if options[:facets][:zeros] == false
24 query_options[:facets][:fields] = options[:facets][:fields].collect{|k| "#{k}_facet"} if options[:facets][:fields]
25 query_options[:filter_queries] = replace_types(options[:facets][:browse].collect{|k| "#{k.sub!(/ *: */,"_facet:")}"}) if options[:facets][:browse]
26 query_options[:facets][:queries] = replace_types(options[:facets][:query].collect{|k| "#{k.sub!(/ *: */,"_t:")}"}) if options[:facets][:query]
27 end
28
29 if models.nil?
30 # TODO: use a filter query for type, allowing Solr to cache it individually
eaa08827 » tomafro
2008-07-17 Added support for single table inheritance within find_by_solr queries
31 models = "AND #{solr_type_condition}"
be5b95d9 » Thiago Jackiw
2008-05-03 git import of acts_as_solr
32 field_list = solr_configuration[:primary_key_field]
33 else
34 field_list = "id"
35 end
36
37 query_options[:field_list] = [field_list, 'score']
38 query = "(#{query.gsub(/ *: */,"_t:")}) #{models}"
39 order = options[:order].split(/\s*,\s*/).collect{|e| e.gsub(/\s+/,'_t ').gsub(/\bscore_t\b/, 'score') }.join(',') if options[:order]
40 query_options[:query] = replace_types([query])[0] # TODO adjust replace_types to work with String or Array
41
42 if options[:order]
43 # TODO: set the sort parameter instead of the old ;order. style.
44 query_options[:query] << ';' << replace_types([order], false)[0]
45 end
eaa08827 » tomafro
2008-07-17 Added support for single table inheritance within find_by_solr queries
46
be5b95d9 » Thiago Jackiw
2008-05-03 git import of acts_as_solr
47 ActsAsSolr::Post.execute(Solr::Request::Standard.new(query_options))
48 rescue
49 raise "There was a problem executing your search: #{$!}"
50 end
51 end
52
eaa08827 » tomafro
2008-07-17 Added support for single table inheritance within find_by_solr queries
53 def solr_type_condition
54 subclasses.inject("(#{solr_configuration[:type_field]}:#{self.name}") do |condition, subclass|
55 condition << " OR #{solr_configuration[:type_field]}:#{subclass.name}"
56 end << ')'
57 end
58
be5b95d9 » Thiago Jackiw
2008-05-03 git import of acts_as_solr
59 # Parses the data returned from Solr
60 def parse_results(solr_data, options = {})
61 results = {
62 :docs => [],
63 :total => 0
64 }
65 configuration = {
66 :format => :objects
67 }
68 results.update(:facets => {'facet_fields' => []}) if options[:facets]
69 return SearchResults.new(results) if solr_data.total == 0
70
71 configuration.update(options) if options.is_a?(Hash)
72
73 ids = solr_data.docs.collect {|doc| doc["#{solr_configuration[:primary_key_field]}"]}.flatten
74 conditions = [ "#{self.table_name}.#{primary_key} in (?)", ids ]
75 result = configuration[:format] == :objects ? reorder(self.find(:all, :conditions => conditions), ids) : ids
76 add_scores(result, solr_data) if configuration[:format] == :objects && options[:scores]
77
78 results.update(:facets => solr_data.data['facet_counts']) if options[:facets]
79 results.update({:docs => result, :total => solr_data.total, :max_score => solr_data.max_score})
80 SearchResults.new(results)
81 end
82
83 # Reorders the instances keeping the order returned from Solr
84 def reorder(things, ids)
85 ordered_things = []
86 ids.each do |id|
87 record = things.find {|thing| record_id(thing).to_s == id.to_s}
88 raise "Out of sync! The id #{id} is in the Solr index but missing in the database!" unless record
89 ordered_things << record
90 end
91 ordered_things
92 end
93
94 # Replaces the field types based on the types (if any) specified
95 # on the acts_as_solr call
96 def replace_types(strings, include_colon=true)
97 suffix = include_colon ? ":" : ""
8bb34400 » tomafro
2008-07-17 Implicitly guess type based on column type if not explicitly set. Als…
98 if configuration[:solr_fields]
99 configuration[:solr_fields].each do |name, options|
100 field = "#{name.to_s}_#{get_solr_field_type(options[:type])}#{suffix}"
101 strings.each_with_index {|s,i| strings[i] = s.gsub(/#{name.to_s}_t#{suffix}/,field) }
be5b95d9 » Thiago Jackiw
2008-05-03 git import of acts_as_solr
102 end
103 end
104 strings
105 end
106
107 # Adds the score to each one of the instances found
108 def add_scores(results, solr_data)
109 with_score = []
110 solr_data.docs.each do |doc|
111 with_score.push([doc["score"],
112 results.find {|record| record_id(record).to_s == doc["#{solr_configuration[:primary_key_field]}"].to_s }])
113 end
114 with_score.each do |score,object|
115 class <<object; attr_accessor :solr_score; end
116 object.solr_score = score
117 end
118 end
119 end
120 end
Something went wrong with that request. Please try again.