module Sunspot module DSL # # This DSL exposes the functionality provided by Solr's fulltext Dismax # handler. # class Fulltext def initialize(query, setup) #:nodoc: @query, @setup = query, setup @fields_added = false end # # Specify which fields to search. Field names specified as arguments are # given default boost; field boosts can be specified by passing a hash of # field names keyed to boost values as the last argument. # # If you wish to boost certain fields without restricting which fields are # searched, use #boost_fields # # === Example # # Sunspot.search(Post) do # keywords 'search is cool' do # fields(:body, :title => 2.0) # end # end # # This would search the :body field with default boost (1.0), and the :title # field with a boost of 2.0 # def fields(*field_names) @fields_added = true boosted_fields = field_names.pop if field_names.last.is_a?(Hash) field_names.each do |field_name| @setup.text_fields(field_name).each do |field| @query.add_fulltext_field(field, field.default_boost) end end if boosted_fields boosted_fields.each_pair do |field_name, boost| @setup.text_fields(field_name).each do |field| @query.add_fulltext_field(field, boost) end end end end # # Enable keyword highlighting for this search. By default, the fields # under search will be highlighted; you may also may pass one or more # symbol arguments indicating fields to be highlighted (they don't even # have to be the same fields you're searching). # # === Example # # Sunspot.search(Post) do # keywords 'show me the highlighting' do # highlight :title, :body # end # end # # You may also pass a hash of options as the last argument. Options are # the following: # # Full disclosure: I barely understand what these options actually do; # this documentation is pretty much just copied from the # (http://wiki.apache.org/solr/HighlightingParameters#head-23ecd5061bc2c86a561f85dc1303979fe614b956)[Solr Wiki] # # :max_snippets:: # The maximum number of highlighted snippets to generate per field # :fragment_size:: # The number of characters to consider for a highlighted fragment # :merge_continuous_fragments:: # Collapse continuous fragments into a single fragment # :phrase_highlighter:: # Highlight phrase terms only when they appear within the query phrase # in the document # :require_field_match:: # If true, a field will only be highlighted if the query matched in # this particular field (only has an effect if :phrase_highlighter is # true as well) # def highlight(*args) options = args.last.kind_of?(Hash) ? args.pop : {} fields = [] args.each { |field_name| fields.concat(@setup.text_fields(field_name)) } @query.set_highlight(fields, options) end # # Phrase fields are an awesome dismax feature that adds extra boost to # documents for which all the fulltext keywords appear in close proximity # in one of the given fields. Excellent for titles, headlines, etc. # # Boosted fields are specified in a hash of field names to a boost, as # with the #fields and #boost_fields methods. # # === Example # # Sunspot.search(Post) do # keywords 'nothing reveals like relevance' do # phrase_fields :title => 2.0 # end # end # def phrase_fields(boosted_fields) if boosted_fields boosted_fields.each_pair do |field_name, boost| @setup.text_fields(field_name).each do |field| @query.add_phrase_field(field, boost) end end end end # # Boost queries allow specification of an arbitrary scope for which # matching documents should receive an extra boost. The block is evaluated # in the usual scope DSL, and field names are attribute fields, not text # fields, as in other scope. # # === Example # # Sunspot.search(Post) do # keywords 'super fan' do # boost(2.0) do # with(:featured, true) # end # end # end # # In the above search, featured posts will receive a boost of 2.0. # def boost(factor, &block) Sunspot::Util.instance_eval_or_call( Scope.new(@query.create_boost_query(factor), @setup), &block ) end # # Add boost to certain fields, without restricting which fields are # searched. # # === Example # # Sunspot.search(Post) do # keywords('pork sandwich') do # boost_fields :title => 1.5 # end # end # def boost_fields(boosts) boosts.each_pair do |field_name, boost| @setup.text_fields(field_name).each do |field| @query.add_fulltext_field(field, boost) end end end def fields_added? #:nodoc: @fields_added end end end end