Every now and then, I run across a gem that I end up using in nearly every project. As it turns out, several of the recent projects I have worked on have required some form of internal site content search engine. While there may be better options out there (like solr), I feel that this is the easiest way to add a search feature on your rails site using a postgres database. My main reason in trying out the postgres search gem (pg_search), was because it is extremely fast and on smaller projects I did not want to have a separate solr server running.

To install pg_search, just include the gem in your Gemfile:

gem 'pg_search'

When using pg_search, there are a multitude of options, but I will discuss the 2 main search features that I found helpful: multisearch and pg_search_scope. You can use one or both of these to get pg_search working, depending on your desired results.

multisearch

Multisearch is a single search command that when run will look at all models that have multisearch enabled and return an array of everything it finds as search objects, not the actual content object. The search objects that are returned in a multisearch include the "searchable_id" which is the actual object ID and "searchable_type" which is the object class name (ie. "Post"). From these bits of information, we can obviously look up the correct Post using its ID. This method of searching is nice because you can specify what attributes you would like to search for each model individually, so you have control over what fields are searched.

Before using multisearch you will want to run the generator to create a migration for the multisearch result documents.

rails g pg_search:migration:multisearch
rake db:migrate

Next you will want to attach pg_search to the model that you would like to search (we will do this in our Post model):

class Post < ActiveRecord::Base
  attr_accessible :body, :title
  include PgSearch
  multisearchable :against => [:body, :title]
end

Thats is for multisearch, now just call the searcher and check out the results:

results = PgSearch.multisearch("foo")

pg_search_scope

Pg_search_scope is another method of searching that acts more like a model scope that you can call to get more specific results from a given model. With this method of searching, you will add a named search scope to the model and when called, it will return a list of the actual objects that if finds. You also have options to declare what attributes should be considered more relavent than others to order the results - for instance, place results with matches in the title ('A') higher than those with matches in the body ('B') of a post. This method can be used for more granular results, but will only return matches from the model that it is called on. You can also have multiple named pg_search_scope methods in the same model, as long as they have different names.

To setup a pg_search scope, add the following to your model:

class Post < ActiveRecord::Base
  attr_accessible :body, :title

  include PgSearch
  pg_search_scope :custom_search,
    :against => {
      :title => 'A',
      :body => 'B'
    },
    :using => {
      :tsearch => {:prefix => true}
    }
end

Thats is for pg_search_scope, now just call the searcher and check out the results:

results = Post.custom_search("foo")

Thats it!

You can now run searches in your app and focus on specific models with specific attributes as well as prioritize the results to suit your needs.

To find out more about the pg_search gem, check out the github page:

https://github.com/Casecommons/pg_search

JD Warren is a Ruby on Rails developer and extensive hardware hacker. Prior to joining isotope|eleven, he was a builder focusing on remodeling apartments and rental houses. In his spare time, JD builds robots, electronic circuits, and is a technical writer with work in several online and print publications and a recent book titled "Arduino Robotics".