Development

Rails Search Gems: Searchkick vs Pg_Search

By December 22, 2015 No Comments

Whenever I hear someone say, “We need a search box on our site”, my heart slightly jumps out of my chest. Achieving quality search results is difficult to do, especially when dealing with different technologies from project to project. Google has set a high standard for how a search engine should work, so many expect this kind of search quality with their website as well.

With a custom web application written in Ruby on Rails, search functionality gets more complicated because you typically don’t have a content management system that has already done the work for you. If the site is only public-facing, it’s easy – simply add a Google Custom Search engine to a site and attain the Google-standard in terms of results. However, once you need to differentiate results for registered users, the task gets more complicated. There are several, great search options with Rails, and I’ll highlight two key gems to utilize.

Pg_Search

One of the best features of Postgres is the built-in, full-text search capabilities. The pg_search gem helps maximize these capabilities by providing a powerful, yet simple, search capability. pg_search is great for a basic search that will search multiple models, associations, and is able to hook into advanced Postgres features in the optional contrib package. This contrib package allows fuzzy and trigram searching.

The setup process to get pg_search rolling is fairly simple:

 

gem ‘pg_search’

 

Run the install migration to allow you to search multiple models at the same time:

 

rails g pg_search:migration:multisearch
rake db:migrate

 

Include the pg_search module in each model you want to be searched:

 

include pg_search

 

Now tell pg_search which fields to search in your model:

 

pg_search_scope :search_page_fields, :against => [:title, :description, :summary]

 

Then run a search:

 

Page.search_page_fields(“search these keywords”)

Searchkick and Elasticsearch

Elasticsearch is a search server that you can run as a service from your web server to return results for a specific search query. Utilizing the searchkick gem allows Rails developers to optimize their search functionality using Elasticsearch. Elasticsearch runs as a separate, local service you can send GET requests to and receive data back in the form of JSON. It’s fast, can be run on pretty much any server setup, and can be setup to run as a dedicated search service using Amazon’s Elasticsearch Service. Elasticsearch utilizes the powerful Lucene search engine to help provide extremely accurate searches.

Server Installation

Linux server setup is pretty simple:

 

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

sudo update-rc.d elasticsearch defaults 95 10
sudo /etc/init.d/elasticsearch start

 

I restarted the server after installation – just to make sure everything was working correctly.

Searchkick Project Setup

Once Elasticsearch is installed, Searchkick implementation is even easier:

 

gem ‘searchkick’

 

Be sure to add the Searchkick capabilities in all the models you want to be searchable. Searchkick takes care of updating the search index automatically which makes setup a breeze. Just add the following link to search model:

 

searchkick

 

Then conduct a search:

 

Page.search("page name here")

 

Elasticsearch Gotchas

While the initial setup was pretty simple, there were a few items that caused problems along the way.

Search Query Limits

Typically search indexes can grow to be quite large, depending on the type of data that’s being searched. By default, Elasticsearch limits search results at 10,000 records, while Searchkick limits to 1,000 results. Using Searchkick, you can easily increase the limit to 10,000 using the “limit” parameter when conducting a search – otherwise you’ll get a nasty exception if you go over that limit.

Multi-Model Search

With a complex search query, one might need to search multiple models – this is pretty simple to do with Searchkick:

 

Page.search(“keyword to search”, :index_name => Searchkick.client.indices.get_aliases.keys)

 

With a custom web-application, you often want to search multiple models and filter specific fields. Building a “filter screen” with different drop downs to filter results, along with a keyword search, can be challenging, but is easily accomplished with Elasticsearch and Searchkick:

 

Page.search(“keywords to search”, where: {or: []{:"_type" => 'user', :is_active => true}, {:"_type" => 'page'}[]}, :index_name => Searchkick.client.indices.get_aliases.keys)

 

Which Rails gem is best for my project?

Each gem is beneficial in different ways. The pg_search gem is incredibly easy to set up, has a nicer syntax, and quickly allows you to search associations and multiple models. The keyword search is not perfect, but is a great way to quickly and efficiently get search functionality off the ground.

 

Searchkick is fantastic because it leverages Elasticsearch and Lucene – so the results are extremely accurate. Elasticsearch is a powerful search service and technology that will continue to be improved upon in the coming years. However, it often takes more setup time and can be tough to get the desired search results, simply because there’s more configuration that can be done. While use-case scenarios may differ, you can never go wrong with Elasticsearch.

Web Application Startup Guide

A 30-page ebook that covers positioning, marketing, pricing, and building your startup product, plus more.