How do I do full-text searching in Ruby on Rails?

I can recommend Sphinx. Ryan Bates has a great screencast on using the Thinking Sphinx plugin to create a full-text search solution.


There are several options available and each have different strengths and weaknesses. If you would like to add full-text searching, it would be prudent to investigate each a little bit and try them out to see how well it works for you in your environment.

MySQL has built-in support for full-text searching. It has online support meaning that when new records are added to the database, they are automatically indexed and will be available in the search results. The documentation has more details.

acts_as_tsearch offers a wrapper for similar built-in functionality for recent versions of PostgreSQL

For other databases you will have to use other software.

Lucene is a popular search provider written in Java. You can use Lucene through its search server Solr with Rails using acts_as_solr.

If you don't want to use Java, there is a port of Lucene to Ruby called Ferret. Support for Rails is added using the acts_as_ferret plugin.

Xapian is another good option and is supported in Rails using the acts_as_xapian plugin.

Finally, my preferred choice is Sphinx using the Ultrasphinx plugin. It is extremely fast and has many options on how to index and search your databases, but is no longer being actively maintained.

Another plugin for Sphinx is Thinking Sphinx which has a lot of positive feedback. It is a little easier to get started using Thinking Sphinx than Ultrasphinx. I would suggest investigating both plugins to determine which fits better with your project.


You can use Ferret (which is Lucene written in Ruby). It integrates seamless with Rails using the acts_as_ferret mixin. Take a look at "How to Integrate Ferret With Rails". A alternative is Sphinx.


Two main options, depending on what you're after.

1) Full Text Indexing and MATCH() AGAINST().

If you're just looking to do a fast search against a few text columns in your table, you can simply use a full text index of those columns and use MATCH() AGAINST() in your queries.

  1. Create the full text index in a migration file:

     add_index :table, :column, type: :fulltext
    
  2. Query using that index:

     where( "MATCH( column ) AGAINST( ? )", term )
    

2) ElasticSearch and Searchkick

If you're looking for a full blown search indexing solution that allows you to search for any column in any of your records while still being lightning quick, take a look at ElasticSearch and Searchkick.

ElasticSearch is the indexing and search engine.

Searchkick is the integration library with Rails that makes it very easy to index your records and search them.

Searchkick's README does a fantastic job at explaining how to get up and running and to fine tune your setup, but here is a little snippet:

  1. Install and start ElasticSearch.

     brew install elasticsearch
     brew services start elasticsearch
    
  2. Add searchkick gem to your bundle:

     bundle add searchkick --strict
    

    The --strict option just tells Bundler to use an exact version in your Gemfile, which I highly recommend.

  3. Add searchkick to a model you want to index:

     class MyModel < ApplicationRecord
       searchkick
     end
    
  4. Index your records.

     MyModel.reindex
    
  5. Search your index.

     matching_records = MyModel.search( "term" )