Module: Solrsan::Search::ClassMethods

Defined in:
lib/solrsan/search.rb,
lib/solrsan/search.rb,
lib/solrsan/indexer.rb

Constant Summary collapse

HL_START_TAG =
"<mark>"
HL_END_TAG =
"</mark>"

Instance Method Summary collapse

Instance Method Details

#destroy_all_index_documents!Object



73
74
75
76
77
# File 'lib/solrsan/indexer.rb', line 73

def destroy_all_index_documents!
  self.perform_solr_command do |rsolr|
    rsolr.delete_by_query("type:#{self.solr_type}")
  end
end

#destroy_index_document(doc) ⇒ Object



63
64
65
66
67
68
69
70
71
# File 'lib/solrsan/indexer.rb', line 63

def destroy_index_document(doc)
  if doc.respond_to?(:solr_id_value)
    self.perform_solr_command do |rsolr|
      rsolr.delete_by_query("id:#{doc.solr_id_value}")
    end
  else
    raise "Object must include Solrsan::Search"
  end
end

#embed_highlighting(search_response) ⇒ Object



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
# File 'lib/solrsan/search.rb', line 142

def embed_highlighting(search_response)
  return search_response unless search_response[:highlighting]

  excluded_highlighting_fields = ['id', 'db_id', 'type']
  #save original pagniate keys
  per_page = search_response[:docs].per_page
  start = search_response[:docs].start
  total = search_response[:docs].total

  highlighted_docs = search_response[:docs].map do |doc|
     = search_response[:highlighting][doc['id']]

    .drop_while{|k,v| excluded_highlighting_fields.include?(k) }.each do |k,v|
      new_value = if doc[k].is_a?(Array)
        matched = v.map{|t| t.gsub(HL_START_TAG,"").gsub(HL_END_TAG,"") }
        v.concat(doc[k].drop_while{|text| matched.include?(text) })
      else
        v
      end
      doc[k] = new_value
    end if 

    doc
  end

  search_response[:docs] = highlighted_docs

  search_response
end

#index_allObject



57
58
59
60
61
# File 'lib/solrsan/indexer.rb', line 57

def index_all
  self.find_in_batches(:batch_size => 100) do |group|
    self.index(group)
  end
end

#key_value_query(key, value) ⇒ Object



98
99
100
101
102
103
104
# File 'lib/solrsan/search.rb', line 98

def key_value_query(key, value)
  if value.starts_with?("[")
    "#{key}:#{value}"
  else
    "#{key}:\"#{value}\""
  end
end

#map_facet_array_to_facet_hash(facet_collection) ⇒ Object

solr facet_fields comes in tuple array format []



134
135
136
137
138
139
140
# File 'lib/solrsan/search.rb', line 134

def map_facet_array_to_facet_hash(facet_collection)
  if facet_collection.is_a?(Array)
    facet_collection.each_slice(2).reduce({}){|acc, tuple| acc[tuple[0]] = tuple[1]; acc}
  else
    facet_collection
  end
end

#parse_element_in_fq(element) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/solrsan/search.rb', line 82

def parse_element_in_fq(element)
  if element.is_a?(String)
    element
  elsif element.is_a?(Hash)
    element.map do |k,values|
      if values.is_a?(String)
        key_value_query(k,values)
      else
        values.map{|value| key_value_query(k,value) }
      end
    end
  else
    raise "each fq parameter must be a string or hash"
  end
end

#parse_facet_counts(facet_counts) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/solrsan/search.rb', line 106

def parse_facet_counts(facet_counts)
  return {} unless facet_counts
  
  if facet_counts['facet_fields']
    facet_counts['facet_fields'] = facet_counts['facet_fields'].reduce({}) do |acc, facet_collection|
      acc[facet_collection[0]] = map_facet_array_to_facet_hash(facet_collection[1])
      acc
    end
  end
  
  if facet_counts['facet_queries']
    facet_counts['facet_queries'] = facet_counts['facet_queries'].group_by{|k,v| k.split(":").first}.reduce({}) do |acc, facet_collection|
      facet_name = facet_collection[0]
      values = facet_collection[1]

      acc[facet_name] = values.reduce({}) do |inner_acc, tuple|
        range = tuple[0].split(":")[1]
        inner_acc[range] = tuple[1]
        inner_acc
      end
      acc
    end
  end

  facet_counts
end

#parse_fq(fq) ⇒ Object



71
72
73
74
75
76
77
78
79
80
# File 'lib/solrsan/search.rb', line 71

def parse_fq(fq)
  return [] if fq.nil?
  if fq.is_a?(Hash)
    fq.map{|k,v| parse_element_in_fq({k => v})}.flatten
  elsif fq.is_a?(Array)
    fq.map{|ele| parse_element_in_fq(ele)}.flatten
  else
    raise "fq must be a hash or array"
  end
end

#parse_params_for_solr(search_params = {}) ⇒ Object



39
40
41
42
43
44
45
46
47
48
# File 'lib/solrsan/search.rb', line 39

def parse_params_for_solr(search_params={})
  solr_params = { :echoParams => 'explicit',
    :q => "*:*",
    :facet => "on",
    :'facet.mincount' => 1}.merge(search_params)

  solr_params[:hl] = true unless search_params[:'hl.fl'].blank?
  solr_params[:fq] = ["type:#{solr_type}"] + parse_fq(search_params[:fq])
  solr_params
end

#parse_solr_response(solr_response) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/solrsan/search.rb', line 50

def parse_solr_response(solr_response)
  docs = solr_response['response']['docs']
  parsed_facet_counts = parse_facet_counts(solr_response['facet_counts'])
  highlighting = solr_response['highlighting']

   = {
    :total_count => solr_response['response']['numFound'],
    :start => solr_response['response']['start'],
    :rows => solr_response['responseHeader']['params']['rows'],
    :time => solr_response['responseHeader']['QTime'],
    :status => solr_response['responseHeader']['status'],
    :sort => solr_response['responseHeader']['params']['sort'],
    :debug => solr_response['debug']
  }
  response = {:docs => docs, :metadata =>  ,
   :facet_counts => parsed_facet_counts, :highlighting => highlighting}
  response[:stats] = solr_response['stats'] if solr_response['stats']

  embed_highlighting(response)
end

#perform_solr_command {|@rsolr| ... } ⇒ Object

Yields:

  • (@rsolr)


13
14
15
16
17
# File 'lib/solrsan/search.rb', line 13

def perform_solr_command
  @rsolr ||= Solrsan::Config.instance.rsolr_object
  yield(@rsolr)
  @rsolr.commit
end

#search(search_params = {}) ⇒ Object



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/solrsan/search.rb', line 19

def search(search_params={})
  @rsolr ||= Solrsan::Config.instance.rsolr_object

  start = search_params[:start] || 0
  rows = search_params[:rows] || 20

  solr_params = parse_params_for_solr(search_params)

  begin
    solr_response = @rsolr.paginate(start, rows, 'select', :params => solr_params)
    parse_solr_response(solr_response)
  rescue RSolr::Error::Http => e
    {:docs => [], 
     :metadata => 
      {:error => {:http_status_code => e.response[:status],
                  :http_message_status => RSolr::Error::Http::STATUS_CODES[e.response[:status].to_i],
                  :full_message => e.message}}}
  end
end

#solr_index(doc, opts = {:add_attributes => {:commitWithin => 10}}) ⇒ Object



43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/solrsan/indexer.rb', line 43

def solr_index(doc, opts={:add_attributes => {:commitWithin => 10}})
  solr_docs = []
  if doc.respond_to?(:map)
    solr_docs = doc.map{|document| document.indexed_fields }
  elsif doc.respond_to?(:as_solr_document) && doc.respond_to?(:indexed_fields)
    solr_docs << doc.indexed_fields
  else
    raise "Indexed document must define a as_solr_document method."
  end

  @rsolr ||= Solrsan::Config.instance.rsolr_object
  @rsolr.add(solr_docs, opts)
end

#solr_typeObject



9
10
11
# File 'lib/solrsan/search.rb', line 9

def solr_type
  self.to_s.underscore
end