views:

47

answers:

1

I'm using Thinking Sphinx to power the search on my Rails application.

I know the guide explicitly says that you can't index model methods, but I would like to. Specifically, I have a model whose instances can be tagged through a has_many_through relationship via acts_as_taggable_on_steroids. The important caveat: the model also nests via awesome_nested_set, and I have tags inheriting through the nesting.

Here's how I'm searching for inherited tags:

def inherited_tags
  retval = []
  cat = self
  while (cat = cat.parent)
    retval += cat.tags
  end
  retval.uniq
end

I am able to search by explicit (not inherited) tags using:

define_index do
  indexes title
  indexes tags(:name)
end

This search seems to work just fine, but I'm having trouble combining them to allow users to search using inherited tags as well. Any advice is much appreciated!

+1  A: 

Sphinx can only index data that's in your database, there's no way around that (there is an XML option, but thinking sphinx doesn't support it).

Your best bet is to add a cached attribute to you model that's invisible to users but used for search.

Try something like:

class Category < ActiveRecord::Base
   define_index do
     indexes title
     indexes cached_tags, :as => :tags
   end

   before_validate :cache_tags       

   def ancestors
     if self.parent
       self.parent.ancestors + [self.parent]
     else
       []
     end
   end

   def inherited_tags
     ancestors.map { |cat| cat.tags }.flatten.uniq
   end

   private

   def cache_tags
     self.cached_tags ||= inherited_tags.join(" ")
   end      
end
James Healy
I agree with this assessment of the situation, James. A practical solution would necessarily be slightly more complicated for the sake of performance (for instance, in your solution, adding a tag in a root category would not updated cache tags for ancestors, and introducing such bubbling would cause editing tags for a root category to be rather slow). I would probably either edit the rake task that updates the thinking sphinx index to calculate cached tags across the board, or I would put in some native SQL string manipulation to speed it up. Thanks for your work!
Steven Xu