Integrations / Frameworks / Rails / Search

Traditional search implementations tend to have search logic and functionality in the back end. Back-end implementation required for the user to enter a search query, execute the search, then be redirected to a search result page.

Implementing search in the back end is no longer necessary. It’s often harmful to performance because of added network and processing latency. Instead, use Algolia’s UI libraries to perform all search requests directly from the end user’s browser, mobile device, or client. It reduces search latency while offloading your servers at the same time.

To create a real-time search experience, you can use Algolia’s InstantSearch libraries.

Built on top of the JavaScript client, InstantSearch is a set of components to help you build your search. It comes in different flavors for all popular JavaScript frameworks:

The recommended practice is to build a front-end search experience to perform queries directly from the end user browser without going through your server. But there are cases when you need to search in the back end.

A search returns ORM-compliant Rails model objects. Your back end will search through Algolia but then load models directly from the database.

1
2
hits =  Contact.search("jon doe")
p hits

The search method will accept any search parameters as second argument.

1
2
# dynamical search parameters
p Contact.search('jon doe', { hitsPerPage: 5, page: 2 })

Some search parameters can be set in the index settings. This is recommended if you find yourself always passing the same search parameters.

1
2
3
4
5
6
7
8
9
10
class Contact < ActiveRecord::Base
  include AlgoliaSearch

  algoliasearch do
    # default search parameters stored in the index settings
    minWordSizefor1Typo 4
    minWordSizefor2Typos 8
    hitsPerPage 42
  end
end

Each ORM object returned is enriched with highlight_result attribute from Algolia’s raw response. See the highlighting and snippeting documentation for more information.

1
hits[0].highlight_result['first_name']['value']

If you want to retrieve something from the original raw Algolia response, you can access it from the response array.

1
2
3
hits =  Contact.search("jon doe")
p hits.raw_answer['nbHits']
p hits.raw_answer['nbPages']

If you don’t need models, you can avoid loading objects from the database and get the Algolia raw JSON response directly.

1
2
3
4
json_answer = Contact.raw_search("jon doe")
p json_answer
p json_answer['hits']
p json_answer['facets']

Searching in a specific index

Sometimes you may need to specify the index name when searching. It typically occurs when you use the add_index method in your model configuration. In this case, you can pass the index key in the second argument, along with search parameters.

1
2
Book.search 'foo bar', index: 'Book_by_editor'
Book.raw_search 'foo bar', index: 'Book_by_editor'

The replica key is also available. Internally, it’s the same as index but it’s more explicit.

1
2
Book.search 'foo bar', replica: 'Book_by_editor'
Book.raw_search 'foo bar', replica: 'Book_by_editor'

Back end pagination

Even though Algolia highly recommends performing all search (and therefore pagination) operations from your front end using JavaScript, Algolia supports both will_paginate and kaminari as pagination back ends. To use :will_paginate, specify the :pagination_backend in your global configuration:

1
2
3
4
5
AlgoliaSearch.configuration = {
  application_id: 'YourApplicationID',
  api_key: 'YourAdminAPIKey',
  pagination_backend: :will_paginate
}

Then, as long as you use the search method, the returning results will be a paginated set:

1
2
3
4
5
6
7
8
9
# in your controller
@results = MyModel.search('foo', hitsPerPage: 10)

# in your views
# if using will_paginate
<%= will_paginate @results %>

# if using kaminari
<%= paginate @results %>

Faceting

Facets can be retrieved calling the extra facets method of the search array response.

To be able to retrieve facets, the necessary attributes must be defined as attributesForFaceting. Read more in the index settings section.

1
2
3
4
5
hits = Contact.search('jon doe', { facets: '*' })
p hits                    # ORM-compliant array of objects
p hits.facets             # extra method added to retrieve facets
p hits.facets['company']  # facet values+count of facet 'company'
p hits.facets['zip_code'] # facet values+count of facet 'zip_code'
1
2
raw_json = Contact.raw_search('jon doe', { facets: '*' })
p raw_json['facets']

Search for facet values

Sometimes you have so many different values for your facets that you wish you could search through them. Algolia can search for facet values as long as you qualified the searchableAttributes as searchable.

1
Product.search_for_facet_values('category', 'Headphones') # Array of {value, highlighted, count}

This method can also take any parameter that a query accepts. This will adjust the search to only hits which would have matched the query.

1
2
3
4
5
# Only sends back the categories containing red Apple products (and only counts those)
Product.search_for_facet_values('category', 'phone', {
  query: 'red',
  filters: 'brand:Apple'
}) # Array of phone categories linked to red Apple products
Did you find this page helpful?