Module: Sunspot::Rails::Searchable::ClassMethods

Defined in:
lib/sunspot/rails/searchable.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(base) ⇒ Object

:nodoc:



133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/sunspot/rails/searchable.rb', line 133

def self.extended(base) #:nodoc:
  class <<base
    alias_method :search, :solr_search unless method_defined? :search
    alias_method :search_ids, :solr_search_ids unless method_defined? :search_ids
    alias_method :remove_all_from_index, :solr_remove_all_from_index unless method_defined? :remove_all_from_index
    alias_method :remove_all_from_index!, :solr_remove_all_from_index! unless method_defined? :remove_all_from_index!
    alias_method :reindex, :solr_reindex unless method_defined? :reindex
    alias_method :index, :solr_index unless method_defined? :index
    alias_method :index_orphans, :solr_index_orphans unless method_defined? :index_orphans
    alias_method :clean_index_orphans, :solr_clean_index_orphans unless method_defined? :clean_index_orphans
    alias_method :atomic_update, :solr_atomic_update unless method_defined? :atomic_update
    alias_method :atomic_update!, :solr_atomic_update! unless method_defined? :atomic_update!
  end
end

Instance Method Details

#searchable?Boolean

Classes that have been defined as searchable return true for this method.

Returns

true

Returns:

  • (Boolean)


380
381
382
# File 'lib/sunspot/rails/searchable.rb', line 380

def searchable?
  true
end

#solr_atomic_update(updates = {}) ⇒ Object

Update properties of existing records in the Solr index. Atomic updates available only for the stored properties.

Updates (passed as a hash)

updates should be specified as a hash, where key - is the object or the object ID and values is hash with property name/values to be updated.

Examples

class Post < ActiveRecord::Base
  searchable do
    string :title, stored: true
    string :description, stored: true
  end
end

post1 = Post.create(title: 'A Title', description: nil)

# update single property
Post.atomic_update(post1.id => {description: 'New post description'})
Or
Post.atomic_update(post1 => {description: 'New post description'})

Notice

all non-stored properties in Solr index will be lost after update. Read Solr wiki page: wiki.apache.org/solr/Atomic_Updates



312
313
314
# File 'lib/sunspot/rails/searchable.rb', line 312

def solr_atomic_update(updates = {})
  Sunspot.atomic_update(self, updates)
end

#solr_atomic_update!(updates = {}) ⇒ Object

Update properties of existing records in the Solr index atomically, and immediately commits.

See #solr_atomic_update for information on options, etc.



322
323
324
# File 'lib/sunspot/rails/searchable.rb', line 322

def solr_atomic_update!(updates = {})
  Sunspot.atomic_update!(self, updates)
end

#solr_clean_index_orphans(opts = {}) ⇒ Object

Find IDs of records of this class that are indexed in Solr but do not exist in the database, and remove them from Solr. Under normal circumstances, this should not be necessary; this method is provided in case something goes wrong.

Options (passed as a hash)

batch_size<Integer>

Override default batch size with which to load records



364
365
366
367
368
369
370
# File 'lib/sunspot/rails/searchable.rb', line 364

def solr_clean_index_orphans(opts={})
  solr_index_orphans(opts).each do |id|
    new do |fake_instance|
      fake_instance.id = id
    end.solr_remove_from_index
  end
end

#solr_execute_search(options = {}) ⇒ Object



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
# File 'lib/sunspot/rails/searchable.rb', line 384

def solr_execute_search(options = {})
  inherited_attributes = [:include, :select, :scopes]
  options.assert_valid_keys(*inherited_attributes)
  search = yield
  unless options.empty?
    search.build do |query|
      inherited_attributes.each do |attr|
        if options[attr]
          query.data_accessor_for(self).send("#{attr}=", options[attr])
        end
      end
    end
  end
  search.execute
end

#solr_execute_search_ids(options = {}) ⇒ Object



400
401
402
403
# File 'lib/sunspot/rails/searchable.rb', line 400

def solr_execute_search_ids(options = {})
  search = yield
  search.raw_results.map { |raw_result| raw_result.primary_key.to_i }
end

#solr_index(opts = {}) ⇒ Object

Add/update all existing records in the Solr index. The batch_size argument specifies how many records to load out of the database at a time. The default batch size is 50; if nil is passed, records will not be indexed in batches. By default, a commit is issued after each batch; passing false for batch_commit will disable this, and only issue a commit at the end of the process. If associated objects need to indexed also, you can specify include in format accepted by ActiveRecord to improve your sql select performance

Options (passed as a hash)

batch_size<Integer>

Batch size with which to load records. Passing ‘nil’ will skip batches. Default is 50.

batch_commit<Boolean>

Flag signalling if a commit should be done after after each batch is indexed, default is ‘true’

include<Mixed>

include option to be passed to the ActiveRecord find, used for including associated objects that need to be indexed with the parent object, accepts all formats ActiveRecord::Base.find does

first_id

The lowest possible ID for this class. Defaults to 0, which is fine for integer IDs; string primary keys will need to specify something reasonable here.

Examples

# index in batches of 50, commit after each
Post.index 

# index all rows at once, then commit
Post.index(:batch_size => nil) 

# index in batches of 50, commit when all batches complete
Post.index(:batch_commit => false) 

# include the associated +author+ object when loading to index
Post.index(:include => :author)


257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'lib/sunspot/rails/searchable.rb', line 257

def solr_index(opts={})
  options = {
    :batch_size => Sunspot.config.indexing.default_batch_size,
    :batch_commit => true,
    :include => self.sunspot_options[:include],
    :start => opts.delete(:first_id)
  }.merge(opts)

  if options[:batch_size].to_i > 0
    batch_counter = 0
    self.includes(options[:include]).find_in_batches(**options.slice(:batch_size, :start)) do |records|

      solr_benchmark(options[:batch_size], batch_counter += 1) do
        Sunspot.index(records.select(&:indexable?))
        Sunspot.commit if options[:batch_commit]
      end

      options[:progress_bar].increment!(records.length) if options[:progress_bar]
    end
  else
    Sunspot.index! self.includes(options[:include]).select(&:indexable?)
  end

  # perform a final commit if not committing in batches
  Sunspot.commit unless options[:batch_commit]
end

#solr_index_orphans(opts = {}) ⇒ Object

Return the IDs of records of this class that are indexed in Solr but do not exist in the database. Under normal circumstances, this should never happen, but this method is provided in case something goes wrong. Usually you will want to rectify the situation by calling #clean_index_orphans or #reindex

Options (passed as a hash)

batch_size<Integer>

Override default batch size with which to load records.

Returns

Array

Collection of IDs that exist in Solr but not in the database



340
341
342
343
344
345
346
347
348
349
350
351
352
# File 'lib/sunspot/rails/searchable.rb', line 340

def solr_index_orphans(opts={})
  batch_size = opts[:batch_size] || Sunspot.config.indexing.default_batch_size          

  solr_page = 0
  solr_ids = []
  while (solr_page = solr_page.next)
    ids = solr_search_ids { paginate(:page => solr_page, :per_page => batch_size) }.to_a
    break if ids.empty?
    solr_ids.concat ids
  end

  return solr_ids - self.connection.select_values("SELECT id FROM #{quoted_table_name}").collect(&:to_i)
end

#solr_reindex(options = {}) ⇒ Object

Completely rebuild the index for this class. First removes all instances from the index, then loads records and indexes them.

See #index for information on options, etc.



214
215
216
217
# File 'lib/sunspot/rails/searchable.rb', line 214

def solr_reindex(options = {})
  solr_remove_all_from_index
  solr_index(options)
end

#solr_remove_all_from_indexObject

Remove instances of this class from the Solr index.



195
196
197
# File 'lib/sunspot/rails/searchable.rb', line 195

def solr_remove_all_from_index
  Sunspot.remove_all(self)
end

#solr_remove_all_from_index!Object

Remove all instances of this class from the Solr index and immediately commit.



204
205
206
# File 'lib/sunspot/rails/searchable.rb', line 204

def solr_remove_all_from_index!
  Sunspot.remove_all!(self)
end

#solr_search(options = {}, &block) ⇒ Object

Search for instances of this class in Solr. The block is delegated to the Sunspot.search method - see the Sunspot documentation for the full API.

Example

Post.search(:include => [:blog]) do
  keywords 'best pizza'
  with :blog_id, 1
  order :updated_at, :desc
  facet :category_ids
end

Options

:include

Specify associations to eager load

:select

Specify columns to select from database when loading results

Returns

Sunspot::Search

Object containing results, totals, facets, etc.



170
171
172
173
174
# File 'lib/sunspot/rails/searchable.rb', line 170

def solr_search(options = {}, &block)
  solr_execute_search(options) do
    Sunspot.new_search(self, &block)
  end
end

#solr_search_ids(&block) ⇒ Object

Get IDs of matching results without loading the result objects from the database. This method may be useful if search is used as an intermediate step in a larger find operation. The block is the same as the block provided to the #search method.

Returns

Array

Array of IDs, in the order returned by the search



186
187
188
189
190
# File 'lib/sunspot/rails/searchable.rb', line 186

def solr_search_ids(&block)
  solr_execute_search_ids do
    solr_search(&block)
  end
end