Indexing
When indexing your data, the network call to Algolia is synchronous, but the indexing operation on Algolia’s servers is asynchronous. If you want to call the Algolia API asynchronously, use background job managers.
When testing, it’s best to wait for indexing tasks.
Manual indexing with rake
The rake command algoliasearch:reindex looks for all models in your app and indexes them.
1
2
3
4
5
6
$ rake algoliasearch:reindex
Reindexing 1 models: Contact.
Contact
Reindexing 500 records...
Regular reindexing
To reindex all objects in place, use the reindex! class method.
This method sends all entries to the Algolia index.
Any record with the same objectID is replaced, and new ones are added.
This method doesn’t delete records from your index.
To delete them, clear your index before reindexing.
1
2
Contact.clear_index!
Contact.reindex!
Clearing your index deletes all records, but preserves your settings, rules, and synonyms.
This method doesn’t increase the number of records beyond the new objects you want to index, but your index will be briefly empty, which makes your search unavailable.
Zero-downtime reindexing
To reindex all your records without downtime,
including deleted objects, use the reindex class method.
1
Contact.reindex
This method indexes all your records to a temporary index INDEX_NAME.tmp.
After everything is indexed, the temporary index overwrites your production index.
This method guarantees that your index is never empty, but it doubles the number of records in your Algolia application.
If you’re using an index-specific API key,
make sure you’re allowing both INDEX_NAME and INDEX_NAME.tmp.
If you’ve changed settings, rules, or synonyms in the Algolia dashboard,
this method deletes or resets them, because it recreates your index configuration as defined in your Rails project.
To prevent this, turn off check_settings.
Indexing subsets
To index a subset of your records, use model scoping. In this case, it’s better not to use zero-downtime indexing, since it would replace the whole index with just the filtered objects.
Use regular reindexing with reindex!.
1
Contact.where('updated_at > ?', 10.minutes.ago).reindex!
To index a list of objects directly, use index_objects.
1
2
objects = Contact.limit(5)
Contact.index_objects objects
Index single instances
To index a single instance, use the index! instance method.
To remove a model from the Algolia index, use remove_from_index!
1
2
3
4
5
c = Contact.create!(params[:contact])
# Add to Algolia
c.index!
# Remove from Algolia
c.remove_from_index!
Automatic updates
To keep Algolia indices synced with your Rails models, this gem uses these Rails callbacks:
after_validationbefore_saveafter_commit
If you’re bypassing these callbacks in your app, Algolia won’t update your changes. Each time you save or delete a record, it’ll be indexed or removed from the index.
To turn off automatic index updates, change the following options:
1
2
3
4
5
6
7
class Contact < ActiveRecord::Base
  include AlgoliaSearch
  algoliasearch auto_index: false, auto_remove: false do
    attribute :first_name, :last_name, :email
  end
end
Temporarily turn off auto-indexing
To temporarily turn off auto-indexing, use the without_auto_index scope.
This can be helpful to achieve better performance if you’re making many changes.
For example, if you delete all contacts from the index and then create 10,000 new contacts, your app would make 10,001 API requests.
1
2
Contact.delete_all
1.upto(10000) { Contact.create! attributes }
If you turn off automatic indexing and call reindex! after,
your app only makes a few API requests,
since the reindex! method batches the requests automatically.
1
2
3
4
5
6
7
Contact.delete_all
Contact.without_auto_index do
  # Auto-indexing is turned off inside this block
  1.upto(10000) { Contact.create! attributes }
end
# Uses batch operations
Contact.reindex!
Indexing only if attributes have changed
For database-stored attributes, Rails provides a will_save_change_to_ATTRIBUTE? method to detect changes.
Add this method for the all dynamic attributes you defined. Otherwise, Algolia updates every model because it won’t know whether a dynamic attribute was updated.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Contact < ActiveRecord::Base
  include AlgoliaSearch
  algoliasearch do
    attributes :first_name, :email
    attribute :full_name
  end
  def full_name
    "#{first_name} #{last_name}"
  end
  def will_save_change_to_fullname?
    will_save_change_to_first_name? || will_save_name_to_last_name?
  end
end
In Rails versions older than 5.1, this method was called ATTRIBUTE_changed?.
The Algolia gem checks for both method names.
tags and geoloc helpers
The tags or geoloc helpers map to the _tags and _geoloc attributes.
That’s why you need to use double underscores:
will_save_change_to__tagswill_save_change_to__geoloc
1
2
3
4
5
6
7
8
9
10
11
12
class Contact < ActiveRecord::Base
  include AlgoliaSearch
  algoliasearch do
    attributes :first_name, :email
    geoloc :latitude, :longitude
  end
  def will_save_change_to__geoloc?
    will_save_change_to_latitude? || will_save_change_to_longitude?
  end
end
Single will_save_change_to method
If Algolia finds an algolia_dirty? method,
it calls this method instead of all the will_save_change_to_ATTRIBUTE? methods for this model.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Contact < ActiveRecord::Base
  include AlgoliaSearch
  algoliasearch do
    attributes :first_name, :email
    attribute :full_name
  end
  def full_name
    "#{first_name} #{last_name}"
  end
  def algolia_dirty?
    # Return true if the model should be reindexed
  end
end
Conditional indexing
To control the indexing of a record, add constraints with the :if or :unless options.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Post < ActiveRecord::Base
  include AlgoliaSearch
  algoliasearch if: :published?, unless: :deleted? do
  end
  def published?
    # [...]
  end
  def deleted?
    # [...]
  end
end
If you add these constraints, saveObjects and deleteObjects methods are called to keep the index in sync with your database.
Since the gem is stateless and can’t know whether the object doesn’t match your constraints anymore or if it never did, these operations are always performed.
To prevent this, add an ATTRIBUTE_changed? method.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Contact < ActiveRecord::Base
  include AlgoliaSearch
  algoliasearch if: :published do
  end
  def published
    # true or false
  end
  def published_changed?
    # return true only if you know that the 'published' state changed
  end
end