> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Indexing

> Manage Algolia indices with Rails models.

export const Records = () => <Tooltip tip="A record is a searchable object in an Algolia index. Each record consists of named attributes." cta="Algolia records" href="/doc/guides/sending-and-managing-data/prepare-your-data#algolia-records">
    records
  </Tooltip>;

export const Index = () => <Tooltip tip="An Algolia index is a searchable dataset that consists of records and configuration settings. These settings define how the records are searched and ranked.">
    index
  </Tooltip>;

export const Application = () => <Tooltip tip="An Algolia application is a self-contained environment with its own indices, configuration, and API keys. Applications don't share data or settings with each other.">
    application
  </Tooltip>;

When indexing your data, the request 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](/doc/framework-integration/rails/indexing/queues).

When testing, it's best to [wait for indexing tasks](/doc/framework-integration/rails/advanced/dev-and-testing#wait-for-indexing-tasks).

## Manual indexing with `rake`

The rake command `algoliasearch:reindex` looks for all models in your app and indexes them.

```sh Command line icon=square-terminal theme={"system"}
$ 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](/doc/libraries/sdk/v1/methods/clear-objects) before reindexing.

```ruby Ruby icon=code theme={"system"}
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.

```ruby Ruby icon=code theme={"system"}
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 temporarily doubles the number of records in your Algolia <Application />.

If you're using an [index-specific API key](/doc/guides/security/api-keys#api-key-restrictions),
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`](/doc/framework-integration/rails/index-configuration/index-settings#sync-your-settings-with-algolia).

## 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 records.

Use regular reindexing with `reindex!`.

```ruby Ruby icon=code theme={"system"}
Contact.where("updated_at > ?", 10.minutes.ago).reindex!
```

To index a list of objects directly, use `index_objects`.

```ruby Ruby icon=code theme={"system"}
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!`

```ruby Ruby icon=code theme={"system"}
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_validation`
* `before_save`
* `after_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:

```ruby Ruby icon=code theme={"system"}
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.

```ruby Ruby icon=code theme={"system"}
Contact.delete_all
1.upto(10000) { Contact.create!(attributes) }
```

If you turn off automatic indexing and call `reindex!` after,
your app makes fewer API requests,
since the `reindex!` method batches the requests automatically.

```ruby Ruby icon=code theme={"system"}
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.

```ruby Ruby icon=code theme={"system"}
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](/doc/framework-integration/rails/indexing/serializing-models#helpers) map to the `_tags` and `_geoloc` attributes.

That's why you need to use double underscores:

* `will_save_change_to__tags`
* `will_save_change_to__geoloc`

```ruby Ruby icon=code theme={"system"}
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.

```ruby Ruby icon=code theme={"system"}
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.

```ruby Ruby icon=code theme={"system"}
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`](/doc/libraries/sdk/v1/methods/save-objects) and [`deleteObjects`](/doc/libraries/sdk/v1/methods/delete-objects) 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.

```ruby Ruby icon=code theme={"system"}
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
```

## Indexing errors

Any `Record at the position XX objectID=XX is too big` errors during indexing are because you've exceeded the [size limit for records](https://support.algolia.com/hc/en-us/articles/4406981897617-Is-there-a-size-limit-for-my-index-records-).
Reduce the size of your records and try again.
