Module: SolrQuery

Defined in:
lib/solr_query.rb

Constant Summary collapse

SOLR_ESCAPE_CHARACTERS =
%w" \ + - ! ( ) : ; ^ [ ] { } ~ * ? "
SOLR_ESCAPE_REGEXP =
Regexp.new(SOLR_ESCAPE_CHARACTERS.map{|char| Regexp.escape(char)}.join("|"))

Class Method Summary collapse

Class Method Details

.blank?(object) ⇒ Boolean

:nodoc: quick rehash of rails’ object.blank?

Returns:

  • (Boolean)


101
102
103
104
105
106
107
# File 'lib/solr_query.rb', line 101

def blank?(object) #:nodoc: quick rehash of rails' object.blank?
  if object.is_a?(String)
    object !~ /\S/
  else
    object.respond_to?(:empty?) ? object.empty? : !object
  end
end

.build(conditions = {}, keyword_key = :keyword) ⇒ Object

build a query for solr

SolrQuery.build(:keyword => "Feather duster")
=> "feather duster"

SolrQuery.build(:keyword => "clean", :organisation => [organisation1, organisation2])
=> "clean AND organisation:(275 OR 6534)"

SolrQuery.build(:colour => ["red", "pink"], :item_type => ["Toy", "Train"])
=> "colour:(red OR pink) AND item_type:(Toy OR Train)"

or you can specify a different magical key for keyword;

SolrQuery.build({:keyword => "old one", :new_keyword => "new one"}, :new_keyword)
=> "new one AND keyword:(old one)"

if you need to do range queries;

SolrQuery.build(:salary => {:min => "010000", :max => "050000"})
=> "salary:([010000 TO 050000])"

SolrQuery.build(:salary => "010000".."050000")
=> "salary:([010000 TO 050000])"

SolrQuery.build(:surname => {:min => "jacobs")
=> "surname:([jacobs TO *])"


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/solr_query.rb', line 28

def build(conditions = {}, keyword_key=:keyword)
  conditions = conditions.dup # let's not accidentally kill our original params
  query_parts = []
  keyword = conditions.delete(keyword_key) # keyword is magical
  if !blank?(keyword) # ie. !keyword.blank?
    query_parts << "#{solr_value(keyword, true)}"
  end

  conditions.each do |field, value|
    unless value.nil?
      query_parts << "#{field}:(#{solr_value(value)})"
    end
  end
  
  if query_parts.empty?
    return ""
  else
    return query_parts.join(" AND ")
  end
end

.escape_solr_string(string) ⇒ Object



96
97
98
# File 'lib/solr_query.rb', line 96

def escape_solr_string(string)
  string.gsub(SOLR_ESCAPE_REGEXP, "\\\\\\0").strip
end

.solr_range(object) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/solr_query.rb', line 77

def solr_range(object)
  min = max = nil
  if object.is_a?(Hash)
    min = object[:min]
    max = object[:max]
  else
    min = object.first
    max = object.last
  end
  min = solr_value(min) if min
  max = solr_value(max) if max
  
  min ||= "*"
  max ||= "*"
  
  return "[#{min} TO #{max}]"
end

.solr_value(object, downcase = false) ⇒ Object



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
# File 'lib/solr_query.rb', line 49

def solr_value(object, downcase=false)
  if object.is_a?(Array) # case when Array will break for has_manys
    if object.empty?
      string = "NIL" # an empty array should be equivalent to "don't match anything"
    else
      string = object.map do |element|
        solr_value(element, downcase)
      end.join(" OR ")
      downcase = false # don't downcase the ORs
    end
  elsif object.is_a?(Hash) || object.is_a?(Range)
    return solr_range(object) # avoid escaping the *
  elsif defined?(ActiveRecord) && object.is_a?(ActiveRecord::Base)
    string = object.id.to_s
  elsif object.is_a?(String)
    if downcase && (bits = object.split(" OR ")) && bits.length > 1
      return "(#{solr_value(bits, downcase)})"
    else
      string = object
    end
  else
    string = object.to_s
  end
  string.downcase! if downcase
  return escape_solr_string(string)
end