ElasticSearch with Ruby on Rails

Elasticsearch is a platform for distributed search and analysis of data in real time. Its popularity is due to its ease of use, powerful features, and scalability.

elasticsearch.jpg

Elasticsearch supports RESTful operations. This means that you can use HTTP methods (GET, POST, PUT, DELETE, etc.) in combination with an HTTP URI (/collection/entry) to manipulate your data. The intuitive RESTful approach is both developer and user friendly, which is one of the reasons for Elasticsearch's popularity.

Elasticsearch is a free and open source software with a solid company behind it — Elastic. This combination makes it suitable for use in anywhere from personal testing to corporate integration.

This article will introduce you to Elasticsearch and show you how to use it with ruby on rails.

How to install elasticsearch

First, you will need a Java Runtime Environment (JRE) on your pc because Elasticsearch is written in the Java programming language. Elasticsearch requires Java 7 or higher. Elasticsearch recommends Oracle JDK version 1.8.0_73, but the native Ubuntu OpenJDK native package for the JRE works as well.

$ sudo apt-get update

After that, you can install OpenJDK with the command:

$ sudo apt-get install openjdk-7-jre

To verify your JRE is installed and can be used, run the command:

$ java -version

When you advance in using Elasticsearch and you start looking for better Java performance and compatibility, you may opt to install Oracle's proprietary Java (Oracle JDK 8).

$ sudo add-apt-repository -y ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get -y install oracle-java8-installer

Elasticsearch can be downloaded directly from elastic.co in zip, tar.gz, deb, or rpm packages. For Ubuntu, it's best to use the deb (Debian) package which will install everything you need to run Elasticsearch.

Download it in a directory of your choosing with the command:

$ wget https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.7.2.deb

Then install it in the usual Ubuntu way with the dpkg command like this: (example in Ubuntu)

$ sudo dpkg -i elasticsearch-1.7.2.deb

This results in Elasticsearch being installed in /usr/share/elasticsearch/ with its configuration files placed in /etc/elasticsearch and its init script added in /etc/init.d/elasticsearch.

To make sure Elasticsearch starts and stops automatically with the Droplet, add its init script to the default runlevels with the command:

$ sudo update-rc.d elasticsearch defaults

Last thing that you need to do to run elasticsearch:

$ sudo service elasticsearch start

After you install and run elasticsearch, you need to make sure your elstatic search work or not you can test it with this

$ curl -X GET 'http://localhost:9200'

and the result that you got from it is:

{
  "status" : 200,
  "name" : "Sultan",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "1.7.2",
    "build_hash" : "e43676b1385b8125d647f593f7202acbd816e8ec",
    "build_timestamp" : "2015-09-14T09:49:53Z",
    "build_snapshot" : false,
    "lucene_version" : "4.10.4"
  },
  "tagline" : "You Know, for Search"
}

Apply elasticsearch with ruby on rails

We will start with a simple rails application as below.

Create the Rails App

Type the following at the command prompt:

$ rails new elasticsearch_rails
$ cd elasticsearch_rails
$ bundle

Create the Movies Controller

Create the movies controller using the Rails generator, add routes to config/routes.rb, and add methods for showing, creating, and listing movies.

$ rails g controller movies

Then open config/routes.rb and add this resource:

Rails.application.routes.draw do
  resource :movies
end

Now, open app/controllers/movies_controller.rb and add methods to create, view and list movies.

<h1>New Movie</h1>
<%= form_for :movie, url: movies_path do |f| %>
  <% if not @movie.nil? and @movie.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize @movie.errors.count, "error" %> prohibited
      this movie from being saved:</h2>
    <ul>
<% @movie.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
    <% end %>
    </ul>
  </div>
  <% end %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>
<%= link_to "<- Back", movies_path %>

Show Single Movie

Create another file at app/views/movies/show.html.erb

<p>
  <strong>Title:</strong>
  <%= @movie.title %>
</p>
<p>
  <strong>Text:</strong>
  <%= @movie.text %>
</p>
<%= link_to "<- Back", movies_path %>

List All movies Create a third file at app/views/movies/index.html.erb.

<p>
  <strong>Title:</strong>
  <%= @movie.title %>
</p>
<p>
  <strong>Description:</strong>
  <%= @movie.description %>
</p>
<%= link_to "<- Back", movies_path %>

You can now add and view movies. Make sure you start the Rails server and go to http://localhost:3000/movies. Click on “New Movie” and add a few movies. These will be used to test our elastsearch capabilities.

Add Basic Search Gem For ElasticSearch

Create a controller called search, along with a view so you can do something like: /search?q=ruby. So we will use gem in rails application, however we have a lot gem that use with elasticsearch as below:

  • gem "searchkick"
  • gem "chewy"
  • gem "elasticsearch-model"
  • gem "elasticsearch-rails"

With this article I will use gem elasticsearch-model and gem elastisearch-rails. Let's add it into your gem file and run bundle install.

Add Search Controller

Create search controller

$ rails g controller search

Add method below into app/controllers/search

  def search
    query = params[:q]
    @movies = query.nil? ? [] : Movie.search(query)
  end

Integrate Search into Movie

To add the ElasticSearch integration to the Movie model,require 'elasticsearch/model' into config/application.rb and include the main module in Movie class.

class Movie < ApplicationRecord
  include Elasticsearch::Model
  include Elasticsearch::Model::Callbacks
end

Search View

Create a new file at app/views/search/search.html.erb

<h1>Movies Search</h1>
<%= form_for search_path, method: :get do |f| %>
  <p>
    <%= f.label "Search for" %>
    <%= text_field_tag :q, params[:q] %>
    <%= submit_tag "Go", name: nil %>
  </p>
<% end %>
<ul>
  <% @movies.each do |movie| %>
    <li>
      <h3>
        <%= link_to movie.title, movie_path(movie) %>
      </h3>
    </li>
  <% end %>
</ul>

Search Routes

Add search routes at config/routes.rb

get "search", to: "search#search"

You can now go to http://localhost:3000/search and search for any word in the articles you created. Note: If you want to import your database movie to search please run rails console

$ Movie.import

Document


All Rights Reserved