mengu on web programming.

Full Text Search With Ruby on Rails

I'm working on something and I needed a search functionality so I did check out my options. I did not prefer MySQL's full text search functionality as I don't want MySQL to deal with it where there are tools created only for that. I did take a look at [Sphinx](http://sphinxsearch.com/), [Solr](http://lucene.apache.org/solr/) and [ElasticSearch](http://www.elasticsearch.org/). Among three of them I did prefer Solr. Luckily, kudos to [Mat Brown](http://outofti.me/) he had created a Solr gem for Ruby called [Sunspot](https://github.com/outoftime/sunspot) and a Ruby on Rails plugin on top of it called Sunspot Rails. In order to make it compact, I will explain all this with creating a sample Rails application. Creating the Rails Application ---------- Let's create a new Rails application and generate a model and its scaffold. rails new rails_fulltext_search -d mysql cd rails_fulltext_search sudo bundle install rails g scaffold Company name:string city:string state:string country:string Installing Sunspot Rails ---------- Like installing any other Rails plugin or Ruby gem with Rails, we simply add `gem 'sunspot_rails'` to your Gemfile and run `bundle install`. Start Solr instance with `rake sunspot:solr:start` echo "gem 'sunspot_rails'" >> Gemfile sudo bundle install rake sunspot:solr:start A note: If you get an error complaining like "libxml2 not found" from nokogiri, you can do `sudo apt-get install libxml2-dev` and install it on Ubuntu. Indexing the Model ---------- Now that we have a Company model that has 'name, city, state, country' fields. How do we make Solr index it? The following is the answer. class Company < ActiveRecord::Base searchable do text :name string :city string :state string :country end end What does this `text` and `string` do here? When we tell Sunspot that `name` is a `text` field, it automatically tokenizes it, applies default filters and downcases it and we use the `keywords()` method to find indexed `text` data however when we use `string`, it does not do anything and the data marked as string can only be searched as is by the `with()` method. By default, whenever we create new Company objects, they will be indexed automatically. What about our current data? You can index them by running `rake sunspot:solr:reindex` command. How to Implement Search Functionality ---------- Let's add a search action in our companies_controller and create the corresponding view in `/app/views/companies/` called `search.html.erb`. # goes in app/controllers/companies_controller.rb def search if params[:commit] @companies = Company.search do if params[:name]; keywords(params[:name]); end [:city, :state, :country].each do |field| if params[field] != ""; with(field, params[field]); end end end.results end end We implement both searching and displaying results in one action. It's not a must or must not do. Do whatever pleases you. The following is our corresponding view. # app/views/companies/search.html.erb <% if !params[:commit] %>

Search companies

<%= form_tag('/companies/search', :method => 'get') do %>
<%= label_tag :name %>
<%= text_field_tag :name %>
<%= label_tag :city %>
<%= text_field_tag :city %>
<%= label_tag :state %>
<%= text_field_tag :state %>
<%= label_tag :country %>
<%= text_field_tag :country %>
<%= submit_tag 'Search' %>
<% end %> <% else %> <% if @companies %>

Search results

    <% @companies.each do |company| %>
  • <%= link_to company.name, company_path(company) %>
  • <% end %>
<% else %> No companies found. <% end %> <% end %> <%= link_to 'Back', companies_path %> Now add this entry `get '/companies/search'` to your `config/routes.rb` before `resources :companies` line. Congratulations! You now have a Rails application using Solr for full text search! The full application is available at [my github repositories](http://github.com/mengu/rails_fulltext_sample). We are not over here. In the next post, I will explain how to paginate the search results. Please feel free to ask any questions you have and you can [follow me on twitter](http://www.twitter.com/mengukagan).
Did you enjoy this post? You should follow me on twitter here.

Comments

JP said on 30/07/2011 20:41 PM
Nice tutorial! I'll definitely be using this for an app im currently working on!

Mengu Kagan said on 30/07/2011 21:06 PM
glad it did help you, JP. :)

Leave a Response

No HTML allowed. You can use markdown.
Name*:
E-Mail* (not published):
Web site:
Response: