Configuring Elasticsearch On Rails

Pre-requisites:

  • Rails version 4+
  • Elasticsearchsearch version 2.3.2

Make sure you have elasticsearch running.

elasticsearch #on mac
brew services start elasticsearch #on mac
sudo service start elasticsearch #on linux

there are a lot of gem available for integration of elasticsearch with rails. The gem that I am using is called “elasticsearch-rails”.

Install the gem:

In your Gemfile.rb write the following:

gem 'elasticsearch-rails'

save the file and then run

bundle install

Then in the directory app/config/initializers/ make a file “elasticsearch.rb”

and write the following:

config = {
host: "http://localhost:9200/",
transport_options: {
request: { timeout: 5 }
}
}

if File.exists?("config/elasticsearch.yml")
config.merge!(YAML.load_file("config/elasticsearch.yml")[Rails.env].symbolize_keys)
end

Elasticsearch
::Model.client = Elasticsearch::Client.new(config)

If you want to specify, say, different urls for different environments, you can do so by creating a file “elasticsearch.yml” in directory app/config/

and writing something like

development: &default
host: 'http://localhost:9200/'
transport_options:
request:
timeout:
!!integer 300
test:
<<:
*default
staging:
<<:
*default
production:
host:
'http://10.50.11.50/'
transport_options:
request:
timeout:
!!integer 300

The configuration is all done.

Now to use elasticsearch in your models, you have to do the following:

Let’s say there is a model called User. In user.rb:

class User < ActiveRecord::Base
include
Elasticsearch::Model
include Elasticsearch::Model::Callbacks
.
.
.
end

Next define the name of the index in User.rb:

index_name([Rails.env,base_class.to_s.pluralize.underscore].join('_'))

Next, make sure you have some records loaded in the model.

Then from the Rails console, run the following to import all the user records in elasticsearch.

Note: Make sure elasticsearch is running before importing data.

#to get into the rails console use rails c 
User.import(force: true)

You are ready to start searching !!

To search you need to pass the query to search method of Elasticsearch.

#this will return an array of records
User.search("divyanshu").records

By default, Elasticsearch indexes all the attributes present in your model. However, the same can be changed. This is done by modifying the method as_indexed_json().

  1. Indexing selective attributes: This can by done using “only” option which accepts a single value or an array of values. You can specify which attributes you want to be indexed.
#define this method in User.rb
def as_indexed_json(options={})
as_json(
only: [:first_name, :email]
)
end

Save the file and in the “rails console” type the following to get a fresh import.

#this is used to delete index
User.__elasticsearch__.delete_index!
#this is used to create index
User.__elasticsearch__.create_index!
#this is used to import the data into Elasticsearch
User.import #note: No need to pass force: true to import
#to the indexed data of first record 
User.search("divyanshu").records.first.as_indexed_json

2. Indexing associations: this is done using “include” option