Class: ThinkingSphinx::Search

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

Overview

Once you've got those indexes in and built, this is the stuff that matters - how to search! This class provides a generic search interface - which you can use to search all your indexed models at once. Most times, you will just want a specific model's results - to search and search_for_ids methods will do the job in exactly the same manner when called from a model.

Constant Summary

CoreMethods =
%w( == class class_eval extend frozen? id instance_eval
instance_of? instance_values instance_variable_defined?
instance_variable_get instance_variable_set instance_variables is_a?
kind_of? member? method methods nil? object_id respond_to?
respond_to_missing? send should type )
SafeMethods =
%w( partition private_methods protected_methods
public_methods send class )
HashOptions =
[:conditions, :with, :without, :with_all, :without_any]
ArrayOptions =
[:classes, :without_ids]

Instance Attribute Summary (collapse)

Class Method Summary (collapse)

Instance Method Summary (collapse)

Constructor Details

- (Search) initialize(*args)

A new instance of Search



86
87
88
89
90
91
92
93
94
95
96
# File 'lib/thinking_sphinx/search.rb', line 86

def initialize(*args)
  ThinkingSphinx.context.define_indexes

  @array    = []
  @options  = args.extract_options!
  @args     = args

  add_default_scope unless options[:ignore_default]

  populate if @options[:populate]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

- (Object) method_missing(method, *args, &block)



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/thinking_sphinx/search.rb', line 166

def method_missing(method, *args, &block)
  if is_scope?(method)
    add_scope(method, *args, &block)
    return self
  elsif method == :search_count
    merge_search one_class.search(*args), self.args, options
    return scoped_count
  elsif method.to_s[/^each_with_.*/].nil? && !@array.respond_to?(method)
    super
  elsif !SafeMethods.include?(method.to_s)
    populate
  end

  if method.to_s[/^each_with_.*/] && !@array.respond_to?(method)
    each_with_attribute method.to_s.gsub(/^each_with_/, ''), &block
  else
    @array.send(method, *args, &block)
  end
end

Instance Attribute Details

- (Object) args (readonly)

Returns the value of attribute args



28
29
30
# File 'lib/thinking_sphinx/search.rb', line 28

def args
  @args
end

- (Object) options (readonly)

Returns the value of attribute options



28
29
30
# File 'lib/thinking_sphinx/search.rb', line 28

def options
  @options
end

Class Method Details

+ (Object) bundle_searches(enum = nil)



64
65
66
67
68
69
70
71
72
73
74
# File 'lib/thinking_sphinx/search.rb', line 64

def self.bundle_searches(enum = nil)
  bundle = ThinkingSphinx::BundledSearch.new

  if enum.nil?
    yield bundle
  else
    enum.each { |item| yield bundle, item }
  end

  bundle.searches
end

+ (Object) count(*args)

Deprecated. Use ThinkingSphinx.count



49
50
51
52
# File 'lib/thinking_sphinx/search.rb', line 49

def self.count(*args)
  warn 'ThinkingSphinx::Search.count is deprecated. Please use ThinkingSphinx.count instead.'
  ThinkingSphinx.count(*args)
end

+ (Object) facets(*args)

Deprecated. Use ThinkingSphinx.facets



55
56
57
58
# File 'lib/thinking_sphinx/search.rb', line 55

def self.facets(*args)
  warn 'ThinkingSphinx::Search.facets is deprecated. Please use ThinkingSphinx.facets instead.'
  ThinkingSphinx.facets(*args)
end

+ (Object) matching_fields(fields, bitmask)



76
77
78
79
80
81
82
83
84
# File 'lib/thinking_sphinx/search.rb', line 76

def self.matching_fields(fields, bitmask)
  matches   = []
  bitstring = bitmask.to_s(2).rjust(32, '0').reverse

  fields.each_with_index do |field, index|
    matches << field if bitstring[index, 1] == '1'
  end
  matches
end

+ (Object) search(*args)

Deprecated. Use ThinkingSphinx.search



31
32
33
34
# File 'lib/thinking_sphinx/search.rb', line 31

def self.search(*args)
  warn 'ThinkingSphinx::Search.search is deprecated. Please use ThinkingSphinx.search instead.'
  ThinkingSphinx.search(*args)
end

+ (Object) search_for_id(*args)

Deprecated. Use ThinkingSphinx.search_for_ids



43
44
45
46
# File 'lib/thinking_sphinx/search.rb', line 43

def self.search_for_id(*args)
  warn 'ThinkingSphinx::Search.search_for_id is deprecated. Please use ThinkingSphinx.search_for_id instead.'
  ThinkingSphinx.search_for_id(*args)
end

+ (Object) search_for_ids(*args)

Deprecated. Use ThinkingSphinx.search_for_ids



37
38
39
40
# File 'lib/thinking_sphinx/search.rb', line 37

def self.search_for_ids(*args)
  warn 'ThinkingSphinx::Search.search_for_ids is deprecated. Please use ThinkingSphinx.search_for_ids instead.'
  ThinkingSphinx.search_for_ids(*args)
end

+ (Object) warn(message)



60
61
62
# File 'lib/thinking_sphinx/search.rb', line 60

def self.warn(message)
  ::ActiveSupport::Deprecation.warn message
end

Instance Method Details

- (Object) append_to(client)



389
390
391
392
393
# File 'lib/thinking_sphinx/search.rb', line 389

def append_to(client)
  prepare client
  client.append_query query, indexes, comment
  client.reset
end

- (Object) as_json(*args)



109
110
111
112
# File 'lib/thinking_sphinx/search.rb', line 109

def as_json(*args)
  populate
  @array.as_json(*args)
end

- (Object) client



383
384
385
386
387
# File 'lib/thinking_sphinx/search.rb', line 383

def client
  client = options[:client] || config.client

  prepare client
end

- (Integer) current_page

The current page number of the result set. Defaults to 1 if no page was explicitly requested.

Returns:

  • (Integer)


201
202
203
# File 'lib/thinking_sphinx/search.rb', line 201

def current_page
  @options[:page].blank? ? 1 : @options[:page].to_i
end

- (Object) each_with_groupby_and_count(&block) Also known as: each_with_group_and_count



319
320
321
322
323
324
325
326
# File 'lib/thinking_sphinx/search.rb', line 319

def each_with_groupby_and_count(&block)
  populate
  results[:matches].each_with_index do |match, index|
    yield self[index],
      match[:attributes]["@groupby"],
      match[:attributes]["@count"]
  end
end

- (Object) each_with_match(&block)



336
337
338
339
340
341
# File 'lib/thinking_sphinx/search.rb', line 336

def each_with_match(&block)
  populate
  results[:matches].each_with_index do |match, index|
    yield self[index], match
  end
end

- (Object) each_with_weighting(&block)



329
330
331
332
333
334
# File 'lib/thinking_sphinx/search.rb', line 329

def each_with_weighting(&block)
  populate
  results[:matches].each_with_index do |match, index|
    yield self[index], match[:weight]
  end
end

- (String?) error

The Sphinx-reported error, if any.

Returns:



135
136
137
138
# File 'lib/thinking_sphinx/search.rb', line 135

def error
  populate
  @results[:error]
end

- (Boolean) error?

Indication of whether the request resulted in an error from Sphinx.

Returns:

  • (Boolean)

    true if Sphinx reports query error



127
128
129
# File 'lib/thinking_sphinx/search.rb', line 127

def error?
  !!error
end

- (Object) excerpt_for(string, model = nil)



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
# File 'lib/thinking_sphinx/search.rb', line 343

def excerpt_for(string, model = nil)
  if model.nil? && one_class
    model ||= one_class
  end

  populate

  index = options[:index] || "#{model.core_index_names.first}"
  client.excerpts(
    {
      :docs   => [string.to_s],
      :words  => results[:words].keys.join(' '),
      :index  => index.split(',').first.strip
    }.merge(options[:excerpt_options] || {})
  ).first
end

- (Object) facets(*args)



375
376
377
378
379
380
381
# File 'lib/thinking_sphinx/search.rb', line 375

def facets(*args)
  options = args.extract_options!
  merge_search self, args, options
  args << options

  ThinkingSphinx::FacetSearch.new(*args)
end

- (Boolean) first_page?

Returns:

  • (Boolean)


205
206
207
# File 'lib/thinking_sphinx/search.rb', line 205

def first_page?
  current_page == 1
end

- (Object) freeze



103
104
105
106
107
# File 'lib/thinking_sphinx/search.rb', line 103

def freeze
  populate
  @array.freeze
  self
end

- (Object) indexes



310
311
312
313
314
315
316
317
# File 'lib/thinking_sphinx/search.rb', line 310

def indexes
  return options[:index] if options[:index]
  return '*' if classes.empty?

  classes.collect { |klass|
    klass.sphinx_index_names
  }.flatten.uniq.join(',')
end

- (Boolean) last_page?

Returns:

  • (Boolean)


228
229
230
# File 'lib/thinking_sphinx/search.rb', line 228

def last_page?
  next_page.nil?
end

- (Integer?) next_page

The next page number of the result set. If there are no more pages available, nil is returned.

Returns:

  • (Integer, nil)


220
221
222
# File 'lib/thinking_sphinx/search.rb', line 220

def next_page
  current_page >= total_pages ? nil : current_page + 1
end

- (Boolean) next_page?

Returns:

  • (Boolean)


224
225
226
# File 'lib/thinking_sphinx/search.rb', line 224

def next_page?
  !next_page.nil?
end

- (Integer) offset Also known as: offset_value

The current page's offset, based on the number of records per page. Or explicit :offset if given.

Returns:

  • (Integer)


304
305
306
# File 'lib/thinking_sphinx/search.rb', line 304

def offset
  @options[:offset] || ((current_page - 1) * per_page)
end

- (Object) page(page_number)

Kaminari support



210
211
212
213
# File 'lib/thinking_sphinx/search.rb', line 210

def page(page_number)
  @options[:page] = page_number
  self
end

- (Object) per(limit)

Kaminari support



255
256
257
258
# File 'lib/thinking_sphinx/search.rb', line 255

def per(limit)
  @options[:limit] = limit
  self
end

- (Integer) per_page Also known as: limit_value

The amount of records per set of paged results. Defaults to 20 unless a specific page size is requested.

Returns:

  • (Integer)


246
247
248
249
250
# File 'lib/thinking_sphinx/search.rb', line 246

def per_page
  @options[:limit] ||= @options[:per_page]
  @options[:limit] ||= 20
  @options[:limit].to_i
end

- (Object) populate_from_queue(results)



395
396
397
398
399
400
401
# File 'lib/thinking_sphinx/search.rb', line 395

def populate_from_queue(results)
  return if @populated
  @populated = true
  @results   = results

  compose_results
end

- (Boolean) populated?

Indication of whether the request has been made to Sphinx for the search query.

Returns:

  • (Boolean)

    true if the results have been requested.



119
120
121
# File 'lib/thinking_sphinx/search.rb', line 119

def populated?
  !!@populated
end

- (Integer?) previous_page

The previous page number of the result set. If this is the first page, then nil is returned.

Returns:

  • (Integer, nil)


237
238
239
# File 'lib/thinking_sphinx/search.rb', line 237

def previous_page
  current_page == 1 ? nil : current_page - 1
end

- (Integer) query_time

Query time taken

Returns:

  • (Integer)


278
279
280
281
282
283
# File 'lib/thinking_sphinx/search.rb', line 278

def query_time
  populate
  return 0 if @results[:time].nil?

  @query_time ||= @results[:time]
end

- (Boolean) respond_to?(method, include_private = false)

Returns true if the Search object or the underlying Array object respond to the requested method.

Parameters:

  • method (Symbol)

    The method name

Returns:

  • (Boolean)

    true if either Search or Array responds to the method.



192
193
194
# File 'lib/thinking_sphinx/search.rb', line 192

def respond_to?(method, include_private = false)
  super || @array.respond_to?(method, include_private)
end

- (Hash) results

The query result hash from Riddle.

Returns:

  • (Hash)

    Raw Sphinx results



161
162
163
164
# File 'lib/thinking_sphinx/search.rb', line 161

def results
  populate
  @results
end

- (Object) search(*args)



360
361
362
363
364
# File 'lib/thinking_sphinx/search.rb', line 360

def search(*args)
  args << args.extract_options!.merge(:ignore_default => true)
  merge_search ThinkingSphinx::Search.new(*args), self.args, options
  self
end

- (Object) search_for_ids(*args)



366
367
368
369
370
371
372
373
# File 'lib/thinking_sphinx/search.rb', line 366

def search_for_ids(*args)
  args << args.extract_options!.merge(
    :ignore_default => true,
    :ids_only       => true
  )
  merge_search ThinkingSphinx::Search.new(*args), self.args, options
  self
end

- (Object) to_a



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

def to_a
  populate
  @array
end

- (Integer) total_entries Also known as: total_count

The total number of search results available.

Returns:

  • (Integer)


289
290
291
292
293
294
# File 'lib/thinking_sphinx/search.rb', line 289

def total_entries
  populate
  return 0 if @results[:total_found].nil?

  @total_entries ||= @results[:total_found]
end

- (Integer) total_pages Also known as: page_count, num_pages

The total number of pages available if the results are paginated.

Returns:

  • (Integer)


264
265
266
267
268
269
# File 'lib/thinking_sphinx/search.rb', line 264

def total_pages
  populate
  return 0 if @results[:total].nil?

  @total_pages ||= (@results[:total] / per_page.to_f).ceil
end

- (String?) warning

The Sphinx-reported warning, if any.

Returns:



152
153
154
155
# File 'lib/thinking_sphinx/search.rb', line 152

def warning
  populate
  @results[:warning]
end

- (Boolean) warning?

Indication of whether the request resulted in a warning from Sphinx.

Returns:

  • (Boolean)

    true if Sphinx reports query warning



144
145
146
# File 'lib/thinking_sphinx/search.rb', line 144

def warning?
  !!warning
end