Integrations / Frameworks / Rails / Replicas & Multiple Indices
May. 10, 2019

Replicas & Multiple Indices

Replicas

Algolia indices are always sorted so when you search, the matching records are already in the right order. If you want to offer multiple sorting strategies, you need to add replicas.

You can define replica indices using the add_replica method. Use inherit: true on the replica block if you want to inherit settings from the primary index.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Book < ActiveRecord::Base
  attr_protected

  include AlgoliaSearch

  algoliasearch per_environment: true do
    searchableAttributes [:name, :author, :editor]

    # define a replica index to search by `author` only
    add_replica 'Book_by_author', per_environment: true do
      searchableAttributes [:author]
    end

    # define a replica index with custom ordering but same settings than the main block
    add_replica 'Book_custom_order', inherit: true, per_environment: true do
      customRanking ['asc(rank)']
    end
  end

end

Share a single index

It can make sense to share an index between several models.

In case you are adding multiple models to the same index, you must ensure you don’t have conflicting objectIDs. By default, the objectID is the primary key of the model. One solution is to prepend the key with the model class name.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Student < ActiveRecord::Base
  attr_protected

  include AlgoliaSearch

  algoliasearch index_name: 'people', id: :algolia_id do
    # [...]
  end

  private
  def algolia_id
    "student_#{id}" # ensure the teacher & student IDs are not conflicting
  end
end

class Teacher < ActiveRecord::Base
  attr_protected

  include AlgoliaSearch

  algoliasearch index_name: 'people', id: :algolia_id do
    # [...]
  end

  private
  def algolia_id
    "teacher_#{id}" # ensure the teacher & student IDs are not conflicting
  end
end

Notes: If you target a single index from several models, you must never use MyModel.reindex and only use MyModel.reindex!. The reindex method uses a temporary index to perform an atomic reindexing: if you use it, the resulting index will only contain records for the current model because it will not reindex the others.

Target multiple indices

You can index a record in several indices using the add_index method.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Book < ActiveRecord::Base
  attr_protected

  include AlgoliaSearch

  PUBLIC_INDEX_NAME  = "Book_#{Rails.env}"
  SECURED_INDEX_NAME = "SecuredBook_#{Rails.env}"

  # store all books in index 'SECURED_INDEX_NAME'
  algoliasearch index_name: SECURED_INDEX_NAME do
    searchableAttributes [:name, :author]
    # convert security to tags
    tags do
      [released ? 'public' : 'private', premium ? 'premium' : 'standard']
    end

    # store all 'public' (released and not premium) books in index 'PUBLIC_INDEX_NAME'
    add_index PUBLIC_INDEX_NAME, if: :public? do
      searchableAttributes [:name, :author]
    end
  end

  private
  def public?
    released && !premium
  end

end

Did you find this page helpful?