Module: ThinkingSphinx::ActiveRecord::ClassMethods

Defined in:
lib/thinking_sphinx/active_record.rb

Instance Method Summary collapse

Instance Method Details

#add_sphinx_index(name, &block) ⇒ Object



206
207
208
209
210
211
212
213
# File 'lib/thinking_sphinx/active_record.rb', line 206

def add_sphinx_index(name, &block)
  index = ThinkingSphinx::Index::Builder.generate self, name, &block

  unless sphinx_indexes.any? { |i| i.name == index.name }
    add_sphinx_callbacks_and_extend(index.delta?)
    insert_sphinx_index index
  end
end

#core_index_namesObject



238
239
240
241
# File 'lib/thinking_sphinx/active_record.rb', line 238

def core_index_names
  define_indexes
  sphinx_indexes.collect(&:core_name)
end

#define_index(name = nil, &block) ⇒ Object

Allows creation of indexes for Sphinx. If you don’t do this, there isn’t much point trying to search (or using this plugin at all, really).

An example or two:

define_index
  indexes :id, :as => :model_id
  indexes name
end

You can also grab fields from associations - multiple levels deep if necessary.

define_index do
  indexes tags.name, :as => :tag
  indexes articles.content
  indexes orders.line_items.product.name, :as => :product
end

And it will automatically concatenate multiple fields:

define_index do
  indexes [author.first_name, author.last_name], :as => :author
end

The #indexes method is for fields - if you want attributes, use #has instead. All the same rules apply - but keep in mind that attributes are for sorting, grouping and filtering, not searching.

define_index do
  # fields ...

  has created_at, updated_at
end

One last feature is the delta index. This requires the model to have a boolean field named ‘delta’, and is enabled as follows:

define_index do
  # fields ...
  # attributes ...

  set_property :delta => true
end

Check out the more detailed documentation for each of these methods at ThinkingSphinx::Index::Builder.



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/thinking_sphinx/active_record.rb', line 161

def define_index(name = nil, &block)
  self.sphinx_index_blocks ||= []
  self.sphinx_indexes      ||= []
  self.sphinx_facets       ||= []

  ThinkingSphinx.context.add_indexed_model self

  if sphinx_index_blocks.empty?
    before_validation :define_indexes
    before_destroy    :define_indexes
  end

  self.sphinx_index_blocks << lambda {
    add_sphinx_index name, &block
  }

  include ThinkingSphinx::ActiveRecord::Scopes
  include ThinkingSphinx::SearchMethods
end

#define_indexesObject



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/thinking_sphinx/active_record.rb', line 181

def define_indexes
  superclass.define_indexes unless superclass == ::ActiveRecord::Base

  return if sphinx_index_blocks.nil? ||
    defined_indexes?                 ||
    !ThinkingSphinx.define_indexes?

  sphinx_index_blocks.each do |block|
    block.call
  end

  self.defined_indexes = true

  # We want to make sure that if the database doesn't exist, then Thinking
  # Sphinx doesn't mind when running non-TS tasks (like db:create, db:drop
  # and db:migrate). It's a bit hacky, but I can't think of a better way.
rescue StandardError => err
  case err.class.name
  when "Mysql::Error", "Mysql2::Error", "Java::JavaSql::SQLException", "ActiveRecord::StatementInvalid"
    return
  else
    raise err
  end
end

#delete_in_index(index, document_id) ⇒ Object



270
271
272
273
274
275
276
277
278
279
# File 'lib/thinking_sphinx/active_record.rb', line 270

def delete_in_index(index, document_id)
  return unless ThinkingSphinx.sphinx_running?

  ThinkingSphinx::Configuration.instance.client.update(
    index, ['sphinx_deleted'], {document_id => [1]}
  )
rescue Riddle::ConnectionError, Riddle::ResponseError,
  ThinkingSphinx::SphinxError, Errno::ETIMEDOUT, Timeout::Error
  # Not the end of the world if Sphinx isn't running.
end

#delta_index_namesObject



243
244
245
246
# File 'lib/thinking_sphinx/active_record.rb', line 243

def delta_index_names
  define_indexes
  sphinx_indexes.select(&:delta?).collect(&:delta_name)
end

#delta_indexed_by_sphinx?Boolean

Returns:

  • (Boolean)


229
230
231
# File 'lib/thinking_sphinx/active_record.rb', line 229

def delta_indexed_by_sphinx?
  sphinx_indexes && sphinx_indexes.any? { |index| index.delta? }
end

#has_sphinx_indexes?Boolean

Returns:

  • (Boolean)


219
220
221
222
223
# File 'lib/thinking_sphinx/active_record.rb', line 219

def has_sphinx_indexes?
  sphinx_indexes      &&
  sphinx_index_blocks &&
  (sphinx_indexes.length > 0 || sphinx_index_blocks.length > 0)
end

#indexed_by_sphinx?Boolean

Returns:

  • (Boolean)


225
226
227
# File 'lib/thinking_sphinx/active_record.rb', line 225

def indexed_by_sphinx?
  sphinx_indexes && sphinx_indexes.length > 0
end

#insert_sphinx_index(index) ⇒ Object



215
216
217
# File 'lib/thinking_sphinx/active_record.rb', line 215

def insert_sphinx_index(index)
  self.sphinx_indexes += [index]
end

#source_of_sphinx_indexObject



257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/thinking_sphinx/active_record.rb', line 257

def source_of_sphinx_index
  define_indexes
  possible_models = self.sphinx_indexes.collect { |index| index.model }
  return self if possible_models.include?(self)

  parent = self.superclass
  while !possible_models.include?(parent) && parent != ::ActiveRecord::Base
    parent = parent.superclass
  end

  return parent
end

#sphinx_index_namesObject



233
234
235
236
# File 'lib/thinking_sphinx/active_record.rb', line 233

def sphinx_index_names
  define_indexes
  sphinx_indexes.collect(&:all_names).flatten
end

#sphinx_offsetObject



281
282
283
284
# File 'lib/thinking_sphinx/active_record.rb', line 281

def sphinx_offset
  ThinkingSphinx.context.superclass_indexed_models.
    index eldest_indexed_ancestor
end

#suspended_delta(reindex_after = true, &block) ⇒ Object

Temporarily disable delta indexing inside a block, then perform a single rebuild of index at the end.

Useful when performing updates to batches of models to prevent the delta index being rebuilt after each individual update.

In the following example, the delta index will only be rebuilt once, not 10 times.

SomeModel.suspended_delta do
  10.times do
    SomeModel.create( ... )
  end
end


301
302
303
304
305
306
307
308
309
310
311
# File 'lib/thinking_sphinx/active_record.rb', line 301

def suspended_delta(reindex_after = true, &block)
  define_indexes
  original_setting = ThinkingSphinx.deltas_suspended?
  ThinkingSphinx.deltas_suspended = true
  begin
    yield
  ensure
    ThinkingSphinx.deltas_suspended = original_setting
    self.index_delta if reindex_after && !original_setting
  end
end

#to_riddleObject



248
249
250
251
252
253
254
255
# File 'lib/thinking_sphinx/active_record.rb', line 248

def to_riddle
  define_indexes
  sphinx_database_adapter.setup

  local_sphinx_indexes.collect { |index|
    index.to_riddle(sphinx_offset)
  }.flatten
end