Elasticsearch is an open-source, RESTful search engine built in Java, but it's possible to use it in Rails as well. Here, I'll walk through getting started with downloading and using it in a simple Rails application, utilizing the Searchkick gem.
Install
If you don't have Java installed, get started by typing in the console:
$ brew install Caskroom/cask/java
This process involves a large download, so if you're not on a fast connection it may take a while. Then you can install Elasticsearch with:
$ brew install elasticsearch
This should also start a download, which finishes with a set of instructions. If you've never used Elasticsearch before, you'll have to load and launch it now:
$ ln -sfv /usr/local/opt/elasticsearch/*.plist ~/Library/LaunchAgents
$ launchctl load ~/Library/LaunchAgents/homebrew.mxcl.elasticsearch.plist
At this point, you can navigate to localhost:9200 and should be able to see a JSON object indicating that you've got Elasticsearch stable and installed on the machine. If you don't see that, pause here and troubleshoot. The Elastic Ruby API Documentation is a helpful resource.
Searchkick
I'm also going to use the Searchkick gem to get our search functionality going, so you can install that by adding to the Gemfile:
gem 'searchkick', '0.8.3'
And run bundle install. Next, we'll need to add the word 'searchkick' to the model we'll be searching. For this example, I've got a yelp-like application with a place model
class Place < ActiveRecord::Base
searchkick
end
If you already have any data within the model you're implementing it for, then you can reindex that information with a rake command.
rake searchkick:reindex CLASS=Place
We'll also need search functionality in the routes.rb file for our places model.
Rails Integration
resources :places do
collection do
get 'search'
end
end
Next, we'll need to add in user functionality to search in the browser. You can do this a variety of ways, but in this application I've already got a header partial that will allow users to search on every page.
<!-- app/views/layouts/_header.html.erb --> <%= form_tag search_places_path, method: :get, class: "navbar-form navbar-right", role: "search" do %> <p> <%= text_field_tag :search, params[:search], class: "form-control" %> <%= submit_tag "Search", name: nil, class: "btn btn-default" %> </p> <% end %>
In the controller, we'll need to add in functionality that tells the application how to search. There are numerous ways to implement this, but I'll just use a basic search method in places_controller.rb
def search
if params[:search].present?
@places = Place.search(params[:search])
else
@places = Places.all
end
Almost finished! At this point, we just need to add in a view file and ensure we have some data to search through. I created a new file similar to places#index:
<!-- app/views/places/search.html.erb --> <% @places.each do |p| %> <%= link_to (image_tag p.image.url(:medium), class: 'image'), p %> <%= p.name %> <% end %>
Now, using the header at the file I can search for various elements of Places in the database, and I should be able to see their image representation and name on the search page. In fact, you can even see the search parameters that were sent through in the URL. For example, if you search for "cafe", it shows: http://localhost:3000/places/search?utf8=%E2%9C%93&search=cafe.
If you have any questions, just let me know. Happy searching!