ThinkingSphinx gives Ruby-on-Rails developers the power of a full-text search engine, with only one downside; it’s a full-text search engine. Recently I had to develop an Advanced Search facility for a site which required me to locate content within certain indexed fields; TS can do this, but it does require a little more configuration than normal.

The Basics

If you’ve never used ThinkingSphinx before, make yourself comfortable, and then visit for the basics of using ThinkingSphinx. The video at RailsCasts is also excellent;

The Problem

The usual usage of ThinkingSphinx is to simply give it the search parameters.

@images = ferarri

This query will return an array containing each image object which has the word ferarri in it. Often, this is sufficient, but consider a model index structure such as

  define_index do
    indexes :name, :as => :asset_name
    indexes description, :as => :desc
    indexes alt_tag, :as => :alttag
    indexes credit
    indexes, :as => :image_type
    indexes, :as => :keywords
    set_property :delta => :datetime, :threshold => 1.hour

There may be occasions where we want to search for the word Ferarri in the name field, but we don’t want to see records where the word ferrari just occured in the description. To do this, we need to place Thinking Sphinx into Extended Mode and restrict the location of the search

@images = @asset_name => ferrari, :match_mode => :extended

If we want to specify multiple search terms across several fields, we add them into the search string seperated by commas;

@images = @asset_name => ferrari, @alttag => Peter, :match_mode => :extended

To specify a string, enclose it in quotes;

@images = @asset_name => ferrari, @alttag => 'Peter Connolly', :match_mode => :extended

That’s fine for hard coded searches, but how do we build this into an advanced search form? Here’s some code snippets that may help Ruby on Rails developers (no – this is not a step-by-step record of how to build advanced search forms, just a series of hints)


For Thinking Sphinx to work, it needs to know which content is to be indexed. We do this by adding a define_index section to the appropriate model (image.rb, in this case)

  define_index do
    indexes :name, :as => :asset_name
    indexes description, :as => :desc
    indexes alt_tag, :as => :alttag
    indexes credit
    indexes, :as => :image_type
    indexes, :as => :keywords
    set_property :delta => :datetime, :threshold => 1.hour


The view will need pagination; for this, we use the will_paginate plugin (walkthrough at

<%# Display the pagination %>
<%= will_paginate @images,
        :inner_window => 1,
        :outer_window => 0,
        :params => {
            'img_type' => @img_type,
            'hidden_id' => @hidden_id,
            'search' => @search_terms,
            'search_title' => @search_title,
            'search_desc' => @search_desc,
            'search_alttag' => @search_alttag,
            'search_credit' => @search_credit,
            'search_imagetype' => @search_imagetype,
            'search_keywords' => @search_keywords

<%# Display the correct set of results %>
<div id="image_library_images">
  <%= render :partial => 'search_image',
             :collection => @images,
             :as => :image


The Advanced form itself uses a standard Rails form

  <div id="advancedsearch" style="display:none;">
    <p><strong>Advanced Image Search options</strong></p>
        <%= label_tag "Title" %>
        <%= text_field_tag :search_title %>
        <%= label_tag "Caption" %>
        <%= text_field_tag :search_desc %>
        <%= label_tag "Alt Tag" %>
        <%= text_field_tag :search_alttag %>
        <%= label_tag "Credit" %>
        <%= text_field_tag :search_credit %>
        <%= label_tag "Image Type" %>
        <%= text_field_tag :search_keywords %>


The controller is where all the heavy lifting occurs for this search function.

  def advanced_search
    @hidden_id = params[:hidden_id] ? params[:hidden_id] : params[:content_type] + '_asset_attributes_primary_image_id'
    @switch_img = params[:img_id] ? params[:img_id] : :primary_image;

    @search_terms = params[:search]  
    @search_title = params[:search_title]
    @search_desc = params[:search_desc]
    @search_alttag = params[:search_alttag]
    @search_credit = params[:search_credit]
    @search_keywords = params[:search_keywords]

    @search = []
    @advsearch = ""

    if (@search_title.present?)
      @advsearch = ' @asset_name => ' + @search_title

    if (@search_desc.present?)
      searchdesc = " @desc => " + @search_desc
      @advsearch += @advsearch.present? ? ", " + searchdesc : searchdesc

    if (@search_alttag.present?)
      searchalttag = " @alttag => " + @search_alttag
      @advsearch += @advsearch.present? ? ", " + searchalttag : searchalttag

    if (@search_credit.present?)
      searchcredit = " @credit => " + @search_credit
      @advsearch += @advsearch.present? ? ", " + searchcredit : searchcredit

    if (@search_keywords.present?)
      searchkeywords = " @keywords => " + @search_keywords
      @advsearch += @advsearch.present? ? ", " + searchkeywords : searchkeywords

    @images = @search_terms + @advsearch,
              :match_mode => :extended,
              :page => params[:page],
              :ignore_errors => false,
              :per_page => 10

    render :partial => 'image_search_results', :layout => false

Indexing Sphinx

This is the mistake that we often make.. After editing data in your database, you will need to reindex Sphinx; otherwise your new data will not be shown the search results.Use the following command to rebuild sphinx from the linux command prompt;

   rake ts:rebuild

Again, please note that the code above is a series of hints, *not* a final, fully fledged solution. Use it as you will, but it’s supplied with no warranty or guarantees. Have fun!