class ThinkingSphinx::FacetSearch

Attributes

args[RW]
options[RW]

Public Class Methods

new(*args) click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 5
def initialize(*args)
  ThinkingSphinx.context.define_indexes
  
  @options      = args.extract_options!
  @args         = args
  
  set_default_options
  
  populate
end

Public Instance Methods

facet_names() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 27
def facet_names
  @facet_names ||= begin
    names = options[:all_facets] ?
      facet_names_for_all_classes : facet_names_common_to_all_classes
    
    names.delete class_facet unless options[:class_facet]
    names
  end
end
for(hash = {}) click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 16
def for(hash = {})
  for_options = {:with => {}}.merge(options)
  
  hash.each do |key, value|
    attrib = ThinkingSphinx::Facet.attribute_name_from_value(key, value)
    for_options[:with][attrib] = underlying_value key, value
  end
  
  ThinkingSphinx.search *(args + [for_options])
end

Private Instance Methods

add_from_results(facet, search) click to toggle source

example: facet = country_facet; name = :country

# File lib/thinking_sphinx/facet_search.rb, line 118
def add_from_results(facet, search)
  name  = ThinkingSphinx::Facet.name_for(facet)
  facet = facet_from_name(facet)
  
  self[name]  ||= {}
  
  return if search.empty?
  
  search.each_with_match do |result, match|
    facet_value = facet.value(result, match[:attributes])
    
    self[name][facet_value] ||= 0
    self[name][facet_value]  += match[:attributes]["@count"]
  end
end
all_facets() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 75
def all_facets
  facet_classes.collect { |klass|
    klass.sphinx_facets
  }.flatten.select { |facet|
    options[:facets].blank? || Array(options[:facets]).include?(facet.name)
  }
end
class_facet() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 166
def class_facet
  Riddle.loaded_version.to_i < 2 ? 'class_crc' : 'sphinx_internal_class'
end
config() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 109
def config
  ThinkingSphinx::Configuration.instance
end
facet_classes() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 67
def facet_classes
  (
    options[:classes] || ThinkingSphinx.context.indexed_models.collect { |model|
      model.constantize
    }
  ).select { |klass| klass.sphinx_facets.any? }
end
facet_from_name(name) click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 159
def facet_from_name(name)
  name = ThinkingSphinx::Facet.name_for(name)
  all_facets.detect { |facet|
    facet.name == name
  }
end
facet_from_object(object, name) click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 145
def facet_from_object(object, name)
  facet = nil
  klass = object.class
  
  while klass != ::ActiveRecord::Base && facet.nil?
    facet = klass.sphinx_facets.detect { |facet|
      facet.attribute_name == name
    }
    klass = klass.superclass
  end
  
  facet
end
facet_names_common_to_all_classes() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 94
def facet_names_common_to_all_classes
  facet_names_for_all_classes.select { |name|
    facet_classes.all? { |klass|
      klass.sphinx_facets.detect { |facet|
        facet.attribute_name == name
      }
    }
  }
end
facet_names_for_all_classes() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 83
def facet_names_for_all_classes
  all_facets.group_by { |facet|
    facet.name
  }.collect { |name, facets|
    if facets.collect { |facet| facet.type }.uniq.length > 1
      raise "Facet #{name} exists in more than one model with different types"
    end
    facets.first.attribute_name
  }
end
facet_search_options(facet_name) click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 56
def facet_search_options(facet_name)
  options.merge(
    :group_function => :attr,
    :limit          => max_matches,
    :max_matches    => max_matches,
    :page           => 1,
    :group_by       => facet_name,
    :ids_only       => !translate?(facet_name)
  )
end
max_matches() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 113
def max_matches
  @max_matches ||= config.configuration.searchd.max_matches || 1000
end
populate() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 46
def populate
  return if facet_names.empty?
  
  ThinkingSphinx::Search.bundle_searches(facet_names) { |sphinx, name|
    sphinx.search *(args + [facet_search_options(name)])
  }.each_with_index { |search, index|
    add_from_results facet_names[index], search
  }
end
set_default_options() click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 39
def set_default_options
  options[:all_facets]  ||= false
  if options[:class_facet].nil?
    options[:class_facet] = ((options[:classes] || []).length != 1)
  end
end
translate?(name) click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 104
def translate?(name)
  facet = facet_from_name(name)
  facet.translate? || facet.float?
end
underlying_value(key, value) click to toggle source
# File lib/thinking_sphinx/facet_search.rb, line 134
def underlying_value(key, value)
  case value
  when Array
    value.collect { |item| underlying_value(key, item) }
  when String
    value.to_crc32
  else
    value
  end
end