lib/thinking_sphinx/search.rb in dpickett-thinking-sphinx-1.1.12 vs lib/thinking_sphinx/search.rb in dpickett-thinking-sphinx-1.1.23
- old
+ new
@@ -1,5 +1,7 @@
+require 'thinking_sphinx/search/facets'
+
module ThinkingSphinx
# Once you've got those indexes in and built, this is the stuff that
# matters - how to search! This class provides a generic search
# interface - which you can use to search all your indexed models at once.
# Most times, you will just want a specific model's results - to search and
@@ -11,10 +13,12 @@
:all_attributes => false,
:class_facet => true
}
class << self
+ include ThinkingSphinx::Search::Facets
+
# Searches for results that match the parameters provided. Will only
# return the ids for the matching objects. See #search for syntax
# examples.
#
# Note that this only searches the Sphinx index, with no ActiveRecord
@@ -216,10 +220,14 @@
# Grouping is done via three parameters within the options hash
# * <tt>:group_function</tt> determines the way grouping is done
# * <tt>:group_by</tt> determines the field which is used for grouping
# * <tt>:group_clause</tt> determines the sorting order
#
+ # As a convenience, you can also use
+ # * <tt>:group</tt>
+ # which sets :group_by and defaults to :group_function of :attr
+ #
# === group_function
#
# Valid values for :group_function are
# * <tt>:day</tt>, <tt>:week</tt>, <tt>:month</tt>, <tt>:year</tt> - Grouping is done by the respective timeframes.
# * <tt>:attr</tt>, <tt>:attrpair</tt> - Grouping is done by the specified attributes(s)
@@ -352,15 +360,13 @@
query = args.clone # an array
options = query.extract_options!
retry_search_on_stale_index(query, options) do
results, client = search_results(*(query + [options]))
+
+ log "Sphinx Error: #{results[:error]}", :error if results[:error]
- ::ActiveRecord::Base.logger.error(
- "Sphinx Error: #{results[:error]}"
- ) if results[:error]
-
klass = options[:class]
page = options[:page] ? options[:page].to_i : 1
ThinkingSphinx::Collection.create_from_results(results, page, client.limit, options)
end
@@ -388,13 +394,13 @@
stale_ids |= e.ids # For logging
options[:without_ids] = Array(options[:without_ids]) | e.ids # Actual exclusion
tries = stale_retries_left
- ::ActiveRecord::Base.logger.debug("Sphinx Stale Ids (%s %s left): %s" % [
- tries, (tries==1 ? 'try' : 'tries'), stale_ids.join(', ')
- ])
+ log "Sphinx Stale Ids (%s %s left): %s" % [
+ tries, (tries==1 ? 'try' : 'tries'), stale_ids.join(', ')
+ ]
retry
end
end
@@ -430,25 +436,10 @@
rescue Errno::ECONNREFUSED => err
raise ThinkingSphinx::ConnectionError, "Connection to Sphinx Daemon (searchd) failed."
end
end
- # Model.facets *args
- # ThinkingSphinx::Search.facets *args
- # ThinkingSphinx::Search.facets *args, :all_attributes => true
- # ThinkingSphinx::Search.facets *args, :class_facet => false
- #
- def facets(*args)
- options = args.extract_options!
-
- if options[:class]
- facets_for_model options[:class], args, options
- else
- facets_for_all_models args, options
- end
- end
-
private
# This method handles the common search functionality, and returns both
# the result hash and the client. Not super elegant, but it'll do for
# the moment.
@@ -472,15 +463,18 @@
client.limit = options[:per_page].to_i if options[:per_page]
page = options[:page] ? options[:page].to_i : 1
page = 1 if page <= 0
client.offset = (page - 1) * client.limit
-
+
begin
- ::ActiveRecord::Base.logger.debug "Sphinx: #{query}"
- results = client.query query
- ::ActiveRecord::Base.logger.debug "Sphinx Result: #{results[:matches].collect{|m| m[:attributes]["sphinx_internal_id"]}.inspect}"
+ log "Sphinx: #{query}"
+ results = client.query(query, '*', options[:comment] || '')
+ log "Sphinx Result:"
+ log results[:matches].collect { |m|
+ m[:attributes]["sphinx_internal_id"]
+ }.inspect
rescue Errno::ECONNREFUSED => err
raise ThinkingSphinx::ConnectionError, "Connection to Sphinx Daemon (searchd) failed."
end
return results, client
@@ -516,10 +510,16 @@
end
hash
end
end
+ # Group by defaults using :group
+ if options[:group]
+ options[:group_by] = options[:group].to_s
+ options[:group_function] ||= :attr
+ end
+
[
:max_matches, :match_mode, :sort_mode, :sort_by, :id_range,
:group_by, :group_function, :group_clause, :group_distinct, :cut_off,
:retry_count, :retry_delay, :index_weights, :rank_mode,
:max_query_time, :field_weights, :filters, :anchor, :limit
@@ -640,15 +640,15 @@
attributes = klass ? klass.sphinx_indexes.collect { |index|
index.attributes.collect { |attrib| attrib.unique_name }
}.flatten : []
lat_attr = klass ? klass.sphinx_indexes.collect { |index|
- index.options[:latitude_attr]
+ index.local_options[:latitude_attr]
}.compact.first : nil
lon_attr = klass ? klass.sphinx_indexes.collect { |index|
- index.options[:longitude_attr]
+ index.local_options[:longitude_attr]
}.compact.first : nil
lat_attr = options[:latitude_attr] if options[:latitude_attr]
lat_attr ||= :lat if attributes.include?(:lat)
lat_attr ||= :latitude if attributes.include?(:latitude)
@@ -693,11 +693,11 @@
client.sort_by = order.to_s.concat("_sort")
else
client.sort_by = order.to_s
end
when String
- client.sort_mode = :extended
+ client.sort_mode = :extended unless options[:sort_mode]
client.sort_by = sorted_fields_to_attributes(order, fields)
else
# do nothing
end
@@ -716,76 +716,12 @@
}
string
end
- def facets_for_model(klass, args, options)
- hash = ThinkingSphinx::FacetCollection.new args + [options]
- options = options.clone.merge! facet_query_options
-
- klass.sphinx_facets.inject(hash) do |hash, facet|
- unless facet.name == :class && !options[:class_facet]
- options[:group_by] = facet.attribute_name
- hash.add_from_results facet, search(*(args + [options]))
- end
-
- hash
- end
- end
-
- def facets_for_all_models(args, options)
- options = GlobalFacetOptions.merge(options)
- hash = ThinkingSphinx::FacetCollection.new args + [options]
- options = options.merge! facet_query_options
-
- facet_names(options).inject(hash) do |hash, name|
- options[:group_by] = name
- hash.add_from_results name, search(*(args + [options]))
- hash
- end
- end
-
- def facet_query_options
- config = ThinkingSphinx::Configuration.instance
- max = config.configuration.searchd.max_matches || 1000
-
- {
- :group_function => :attr,
- :limit => max,
- :max_matches => max
- }
- end
-
- def facet_classes(options)
- options[:classes] || ThinkingSphinx.indexed_models.collect { |model|
- model.constantize
- }
- end
-
- def facet_names(options)
- classes = facet_classes(options)
- names = options[:all_attributes] ?
- facet_names_for_all_classes(classes) :
- facet_names_common_to_all_classes(classes)
-
- names.delete "class_crc" unless options[:class_facet]
- names
- end
-
- def facet_names_for_all_classes(classes)
- classes.collect { |klass|
- klass.sphinx_facets.collect { |facet| facet.attribute_name }
- }.flatten.uniq
- end
-
- def facet_names_common_to_all_classes(classes)
- facet_names_for_all_classes(classes).select { |name|
- classes.all? { |klass|
- klass.sphinx_facets.detect { |facet|
- facet.attribute_name == name
- }
- }
- }
+ def log(message, method = :debug)
+ return if ::ActiveRecord::Base.logger.nil?
+ ::ActiveRecord::Base.logger.send method, message
end
end
end
end