module Sunspot module Query module Restriction #:nodoc: class < [to_filter_query] } end # # Return the boolean phrase associated with this restriction object. # Differentiates between positive and negated boolean phrases depending # on whether this restriction is negated. # def to_boolean_phrase value = if negated? to_negated_boolean_phrase else to_positive_boolean_phrase end @field.respond_to?(:local_params) ? @field.local_params(value) : value end # # Boolean phrase representing this restriction in the positive. Subclasses # may choose to implement this method rather than #to_params; however, # this method delegates to the abstract #to_solr_conditional method, which # in most cases will be what subclasses will want to implement. # #to_solr_conditional contains the boolean phrase representing the # condition but leaves out the field name (see built-in implementations # for examples) # # ==== Returns # # String:: Boolean phrase for restriction in the positive # def to_positive_boolean_phrase "#{Util.escape(@field.indexed_name)}:#{to_solr_conditional}" end # # Boolean phrase representing this restriction in the negated. Subclasses # may choose to implement this method, but it is not necessary, as the # base implementation delegates to #to_positive_boolean_phrase. # # ==== Returns # # String:: Boolean phrase for restriction in the negated # def to_negated_boolean_phrase "-#{to_positive_boolean_phrase}" end # # Whether this restriction should be negated from its original meaning # def negated? #:nodoc: !!@negated end # # Return a new restriction that is the negated version of this one. It # is used by disjunction denormalization. # def negate self.class.new(!@negated, @field, @value) end protected # # Return escaped Solr API representation of given value # # ==== Parameters # # value:: # value to convert to Solr representation (default: @value) # # ==== Returns # # String:: Solr API representation of given value # def solr_value(value = @value) solr_value = Util.escape(@field.to_indexed(value)) if RESERVED_WORDS.include?(solr_value) %Q("#{solr_value}") else solr_value end end end class InRadius < Base def initialize(negated, field, *value) @lat, @lon, @radius = value super negated, field, value end def negate self.class.new(!@negated, @field, *@value) end private def to_positive_boolean_phrase "_query_:\"{!geofilt sfield=#{@field.indexed_name} pt=#{@lat},#{@lon} d=#{@radius}}\"" end end class InBoundingBox < Base def initialize(negated, field, first_corner, second_corner) @bbox = Sunspot::Query::Bbox.new(field, first_corner, second_corner) super negated, field, [first_corner, second_corner] end def to_solr_conditional @bbox.to_solr_conditional end end # # Results must have field with value equal to given value. If the value # is nil, results must have no value for the given field. # class EqualTo < Base def to_positive_boolean_phrase unless @value.nil? super else "#{Util.escape(@field.indexed_name)}:[* TO *]" end end def negated? if @value.nil? !super else super end end private def to_solr_conditional @field.respond_to?(:to_solr_conditional) ? @field.to_solr_conditional(solr_value) : "#{solr_value}" end end # # Results must have field with value less than given value # class LessThan < Base private def solr_value(value = @value) solr_value = super solr_value = "\"#{solr_value}\"" if solr_value.index(' ') solr_value end def to_solr_conditional "{* TO #{solr_value}}" end end # # Results must have field with value less or equal to than given value # class LessThanOrEqualTo < Base private def solr_value(value = @value) solr_value = super solr_value = "\"#{solr_value}\"" if solr_value.index(' ') solr_value end def to_solr_conditional "[* TO #{solr_value}]" end end # # Results must have field with value greater than given value # class GreaterThan < Base private def solr_value(value = @value) solr_value = super solr_value = "\"#{solr_value}\"" if solr_value.index(' ') solr_value end def to_solr_conditional "{#{solr_value} TO *}" end end # # Results must have field with value greater than or equal to given value # class GreaterThanOrEqualTo < Base private def solr_value(value = @value) solr_value = super solr_value = "\"#{solr_value}\"" if solr_value.index(' ') solr_value end def to_solr_conditional "[#{solr_value} TO *]" end end # # Results must have field with value in given range # class Between < Base private def solr_value(value = @value) solr_value = super solr_value = "\"#{solr_value}\"" if solr_value.index(' ') solr_value end def to_solr_conditional "[#{solr_value(@value.first)} TO #{solr_value(@value.last)}]" end end # # Results must have field with value included in given collection # class AnyOf < Base def negated? if @value.empty? false else super end end private def to_solr_conditional if @value.empty? "[* TO *]" else "(#{@value.map { |v| to_solr_conditional_per_value v } * ' OR '})" end end def to_solr_conditional_per_value(v) @field.respond_to?(:to_solr_conditional) ? @field.to_solr_conditional(solr_value(v)) : "#{solr_value(v)}" end end # # Results must have field with values matching all values in given # collection (only makes sense for fields with multiple values) # class AllOf < Base def negated? if @value.empty? false else super end end private def to_solr_conditional if @value.empty? "[* TO *]" else "(#{@value.map { |v| solr_value v } * ' AND '})" end end end # # Results must have a field with a value that begins with the argument. # Most useful for strings, but in theory will work with anything. # class StartingWith < Base private def to_solr_conditional "#{solr_value(@value)}*" end end class AbstractRange < Between private def operation @operation || self.class.name.split('::').last end def solr_value(value = @value) @field.to_indexed(value) end def to_positive_boolean_phrase "_query_:\"{!field f=#{@field.indexed_name} op=#{operation}}#{solr_value}\"" end end class Containing < AbstractRange def initialize(negated, field, value) @operation = 'Contains' super end end class Intersecting < AbstractRange def initialize(negated, field, value) @operation = 'Intersects' super end end class Within < AbstractRange end end end end