Class: Enygma::Search

Inherits:
Object
  • Object
show all
Defined in:
lib/enygma/search.rb

Defined Under Namespace

Classes: AmbiguousIndexes, InvalidFilter, InvalidSphinxQuery, MultipleResultSetsError

Constant Summary collapse

MATCH_MODES =
{
  :all        => Sphinx::Client::SPH_MATCH_ALL,
  :any        => Sphinx::Client::SPH_MATCH_ANY,
  :phrase     => Sphinx::Client::SPH_MATCH_PHRASE,
  :boolean    => Sphinx::Client::SPH_MATCH_BOOLEAN,
  :extended   => Sphinx::Client::SPH_MATCH_EXTENDED,
  :full       => Sphinx::Client::SPH_MATCH_FULLSCAN,
  :extended2  => Sphinx::Client::SPH_MATCH_EXTENDED2
}
GROUP_FUNCTIONS =
{
  :day    => Sphinx::Client::SPH_GROUPBY_DAY,
  :week   => Sphinx::Client::SPH_GROUPBY_WEEK, 
  :month  => Sphinx::Client::SPH_GROUPBY_MONTH, 
  :year   => Sphinx::Client::SPH_GROUPBY_YEAR,
  :attr   => Sphinx::Client::SPH_GROUPBY_ATTR,
  :pair   => Sphinx::Client::SPH_GROUPBY_ATTRPAIR
}
SORT_MODES =
{
  :relevance      => Sphinx::Client::SPH_SORT_RELEVANCE,
  :date_desc      => Sphinx::Client::SPH_SORT_ATTR_DESC,
  :date_asc       => Sphinx::Client::SPH_SORT_ATTR_ASC,
  :time_segments  => Sphinx::Client::SPH_SORT_TIME_SEGMENTS,
  :extended       => Sphinx::Client::SPH_SORT_EXTENDED,
  :expression     => Sphinx::Client::SPH_SORT_EXPR
}

Instance Method Summary collapse

Constructor Details

#initialize(*args, &block) ⇒ Search

Returns a new instance of Search.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/enygma/search.rb', line 57

def initialize(*args, &block)
  overrides = args.last.is_a?(Hash) ? args.pop : {}

  config = if args.first.is_a?(Enygma::Configuration)
    args.first
  elsif block_given?
    Enygma::Configuration.new(&block)
  else
    raise NoConfiguration, "You must supply an Enygma::Configuration object or definition block to create an Enygma::Search!"
  end
    
  @database = {
    :adapter  => config.adapter,
    :table    => config.table
  }
  @sphinx   = Sphinx::Client.new

  @indexes      = config.indexes
  @term         = overrides[:term] || ""
  @target_attr  = config.target_attr
  @match_mode   = MATCH_MODES[config.match_mode]
  @key_prefix   = config.key_prefix || ''
  
  @latitude   = config.latitude
  @longitude  = config.longitude

  @limit      = @sphinx.instance_variable_get(:@limit)
  @offset     = @sphinx.instance_variable_get(:@offset)
  @max        = @sphinx.instance_variable_get(:@maxmatches)
  @cutoff     = @sphinx.instance_variable_get(:@cutoff)

  @return_attributes  = []

  @sphinx.SetServer(config.sphinx[:host], config.sphinx[:port])
  @sphinx.SetMatchMode(@match_mode)
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



98
99
100
# File 'lib/enygma/search.rb', line 98

def method_missing(name, *args, &block)
  self.run.__send__(name, *args, &block)
end

Instance Method Details

#anchor(point_or_lat, lng = nil) ⇒ Object



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/enygma/search.rb', line 211

def anchor(point_or_lat, lng = nil)
  if lng.nil?
    if point_or_lat.respond_to?(:lat) && point_or_lat.respond_to?(:lng)
      lat, lng = point_or_lat.lat, point_or_lat.lng
    elsif point_or_lat.respond_to?(:coordinates) && point_or_lat.coordinates.respond_to?(:lat) && point_or_lat.coordinates.respond_to?(:lng)
      lat, lng = point_or_lat.coordinates.lat, point_or_lat.coordinates.lng
    elsif point_or_lat.respond_to?(:point) && point_or_lat.point.respond_to?(:lat) && point_or_lat.point.respond_to?(:lng)
      lat, lng = point_or_lat.point.lat, point_or_lat.point.lng
    else
      raise ArgumentError, "#{point_or_lat.inspect} doesn't seem to be a geometry-enabled object!"
    end
  else
    lat, lng = point_or_lat, lng
  end
  geo_anchor(lat, lng)
  self
end

#countObject



102
103
104
# File 'lib/enygma/search.rb', line 102

def count
  query_sphinx['total']
end

#cutoff(value) ⇒ Object



201
202
203
204
205
# File 'lib/enygma/search.rb', line 201

def cutoff(value)
  @cutoff = value
  set_limits
  self
end

#exclude(attribute, values) ⇒ Object



147
148
149
# File 'lib/enygma/search.rb', line 147

def exclude(attribute, values)
  filter(attribute, values, true)
end

#filter(attribute, values, exclude = false) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/enygma/search.rb', line 128

def filter(attribute, values, exclude = false)
  attribute = attribute.to_s
  case values
  when Array
    @sphinx.SetFilter(attribute, values, exclude)
  when Range
    if values.begin.is_a?(Float) || values.end.is_a?(Float)
      @sphinx.SetFilterFloatRange(attribute, values.begin.to_f, values.end.to_f, exclude)
    else
      @sphinx.SetFilterRange(attribute, values.begin.to_i, values.end.to_i, exclude)
    end
  when Numeric
    @sphinx.SetFilterFloatRange(attribute, 0.0, values.to_f, exclude)
  else
    raise InvalidFilter
  end
  self
end

#for(*terms) ⇒ Object



106
107
108
109
# File 'lib/enygma/search.rb', line 106

def for(*terms)
  @term = terms.join(" ")
  self      
end

#group_by(attribute, function, sort = "@group DESC") ⇒ Object



151
152
153
154
# File 'lib/enygma/search.rb', line 151

def group_by(attribute, function, sort = "@group DESC")
  @sphinx.SetGroupBy(attribute, GROUP_FUNCTIONS[function], sort)
  self
end

#in(table) ⇒ Object



111
112
113
114
# File 'lib/enygma/search.rb', line 111

def in(table)
  @database[:table] = table
  self
end

#limit(value) ⇒ Object



183
184
185
186
187
# File 'lib/enygma/search.rb', line 183

def limit(value)
  @limit = value
  set_limits
  self
end

#max(value) ⇒ Object



195
196
197
198
199
# File 'lib/enygma/search.rb', line 195

def max(value)
  @max = value
  set_limits
  self
end

#offset(value) ⇒ Object



189
190
191
192
193
# File 'lib/enygma/search.rb', line 189

def offset(value)
  @offset = value
  set_limits
  self
end

#runObject



94
95
96
# File 'lib/enygma/search.rb', line 94

def run
  query_database(query_sphinx)
end

#select(*attributes) ⇒ Object



178
179
180
181
# File 'lib/enygma/search.rb', line 178

def select(*attributes)
  @sphinx.SetSelect(attributes.join(','))
  self
end

#sort_by(type, sort_by = '') ⇒ Object



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/enygma/search.rb', line 156

def sort_by(type, sort_by = '')
  case type
  when :date
    if arg == :asc
      sort_mode = :date_asc
    else
      sort_mode = :date_desc
    end
  when :time
    sort_mode = :time_segments
  when :expression
    sort_mode = :expression
  when String
    sort_mode = :extended
    sort_by = type
  else
    sort_mode = :relevance
  end
  @sphinx.SetSortMode(SORT_MODES[sort_mode], sort_by)
  self
end

#using_indexes(*indexes) ⇒ Object Also known as: using_index



122
123
124
125
# File 'lib/enygma/search.rb', line 122

def using_indexes(*indexes)
  @indexes = indexes.collect { |idx| Enygma.indexify(idx) }
  self
end

#using_match_mode(match_mode) ⇒ Object



116
117
118
119
120
# File 'lib/enygma/search.rb', line 116

def using_match_mode(match_mode)
  @match_mode = MATCH_MODES[match_mode]
  @sphinx.SetMatchMode(@match_mode)
  self
end

#within(distance) ⇒ Object



207
208
209
# File 'lib/enygma/search.rb', line 207

def within(distance)
  Enygma::GeoDistanceProxy.new(self, distance)
end