Elasticsearch is a full-text search engine with a RESTful web interface based on Lucene. Elasticsearch is developed in Java and is released as open source under the terms of the Apache License.
Elastic search installation is covered in my previous blog.
Elastic search in rails is split into three separate gems:
elasticsearch-model, which contains search integration for Ruby/Rails models such as ActiveRecord::Base and Mongoidelasticsearch-persistence, which provides a standalone persistence layer for Ruby/Rails objects and modelselasticsearch-rails, which contains various features for Ruby on Rails applications
By default, our Rails app will connect to Elasticsearch at localhost:9200, but if you need to connect to a different server, uses the config/elasticsearch.yml file to overwrite the defaults.
config = {
host: "http://localhost:9800/"
}
if File.exists?("config/elasticsearch.yml")
config.merge!(YAML.load_file("config/elasticsearch.yml").symbolize_keys)
end
Elasticsearch::Model.client = Elasticsearch::Client.new(config)First include elasticsearch in your model, so that elasticsearch methods and callbacks can be used in model.
class Merchant < ActiveRecord::Base
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
endin console execute the code:
2.1.5 :001 > Merchant.search('ram').results.count
=> 2Before searching we have to call a method import on the table we want to search, because initially our search index is empty. By importing all changes will be added to index automatically. So to populate data we need to execute:
Merchant.importBy deafult all columns are looked up in search. But these can be restricted by:
class Merchant < ActiveRecord::Base
def as_indexed_json(options={})
as_json(
only: [:name, :about, :price, :gender]
)
end
endWhen Elasticsearch indexes our Merchant object, we are telling it that we only want to search the name, about, price and gender attribute.
Their are two methods of getting the result.
Merchant.search('ram').results.count
Merchant.search('ram').records.countrecords method will return collection of ActiveRecord objects and results will return collection Elasticsearch objects.
Now lets discuss the case of associations. Let’s have a model opening for merchants:
class Opening < ActiveRecord::Base
belongs_to :merchant
endclass Merchant < ActiveRecord::Base
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
has_many :openings
endFor adding openings in search index lets add that in as_indexed_json method of Merchant
class Merchant < ActiveRecord::Base
include Elasticsearch::Model
include Elasticsearch::Model::Callbacks
has_many :openings
def as_indexed_json(options={})
as_json(
only: [:name, :about, :price, :gender],
include: [:openings]
)
end
endNow all fields of opening models will also be added in index. To add specific column of association modify the method as:
def as_indexed_json(options={})
as_json(
only: [:name, :about, :price, :gender],
include: {openings: {only: [:name, :section]}}
)
endNow try fetch the method in console:
> rails c
2.1.5 :001 > Merchant.first.as_indexed_json
=> {"name"=>"Annu", "about"=>"Software engineer", "gender"=>1, "price"=>100.0, "openings"=>[{"name"=>"tution", "section"=>"C"}, {"name"=>"seminar", "section"=>"java"}]}Now searching can be made for openings fields also. To make methods as searchable alter the as_indexed_json method as:
def as_indexed_json(options={})
as_json(
only: [:name, :about, :price, :gender],
methods: [:availabilities, :specializations_id],
include: {openings: {only: [:name, :section]}}
)
end