Class: Sunspot::Query

Inherits:
Object
  • Object
show all
Defined in:
lib/sunspot/query.rb,
lib/sunspot/query/sort.rb,
lib/sunspot/query/pagination.rb,
lib/sunspot/query/field_facet.rb,
lib/sunspot/query/restriction.rb,
lib/sunspot/query/dynamic_query.rb

Overview

This class encapsulates a query that is to be sent to Solr. The query is constructed in the block passed to the Sunspot.search method, using the Sunspot::DSL::Query interface. It can also be accessed directly by calling #query on a Search object (presumably a not-yet-run one created using Sunspot#new_search), which might be more suitable than the DSL when an intermediate object has responsibility for building the query dynamically. – Instances of Query, as well as all of the components it contains, respond to the #to_params method, which returns a hash of parameters in the format recognized by the solr-ruby API.

Defined Under Namespace

Modules: Restriction Classes: DynamicQuery, FieldFacet, Pagination, Sort

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(types, configuration) ⇒ Query

:nodoc:



21
22
23
24
25
# File 'lib/sunspot/query.rb', line 21

def initialize(types, configuration) #:nodoc:
  @types, @configuration = types, configuration
  @components = []
  @components << @pagination = Pagination.new(@configuration)
end

Instance Attribute Details

#keywords=(value) ⇒ Object (writeonly)

<String> full-text keyword boolean phrase



19
20
21
# File 'lib/sunspot/query.rb', line 19

def keywords=(value)
  @keywords = value
end

Instance Method Details

#add_component(component) ⇒ Object

Add a component to the query. Used by objects that proxy to the query object.

Parameters

component<~to_params>

Query component to add.



120
121
122
# File 'lib/sunspot/query.rb', line 120

def add_component(component) #:nodoc:
  @components << component
end

#add_field_facet(field_name) ⇒ Object

Add a field facet. See Sunspot::Facet for more information.

Parameters

field_name<Symbol>

Name of the field on which to get a facet



86
87
88
# File 'lib/sunspot/query.rb', line 86

def add_field_facet(field_name)
  @components << FieldFacet.new(field(field_name))
end

#add_negated_restriction(field_name, restriction_type, value) ⇒ Object

Add a negated restriction to the query. The restriction will be taken as the opposite of its usual meaning (e.g., an :equal_to restriction will be “not equal to”.

Parameters

field_name<Symbol>

Name of the field to which the restriction applies

restriction_type<Class>

Subclass of Sunspot::Query::Restriction::Base to instantiate

value<Object>

Value against which the restriction applies (e.g. less_than(2) has a value of 2)



64
65
66
# File 'lib/sunspot/query.rb', line 64

def add_negated_restriction(field_name, restriction_type, value)
  add_restriction(field_name, restriction_type, value, true)
end

#add_restriction(field_name, restriction_type, value, negated = false) ⇒ Object

Add a restriction to the query.

Parameters

field_name<Symbol>

Name of the field to which the restriction applies

restriction_type<Class,Symbol>

Subclass of Sunspot::Query::Restriction::Base, or snake_cased name as symbol (e.g., :equal_to)

value<Object>

Value against which the restriction applies (e.g. less_than(2) has a value of 2)

negated

Whether this restriction should be negated (use add_negated_restriction)



42
43
44
45
46
47
48
# File 'lib/sunspot/query.rb', line 42

def add_restriction(field_name, restriction_type, value, negated = false)
  if restriction_type.is_a?(Symbol)
    restriction_type = Restriction[restriction_type]
  end
  @components << restriction = restriction_type.new(field(field_name), value, negated)
  restriction
end

#build(&block) ⇒ Object

Build the query using the DSL block passed into Sunspot.search

Returns

Sunspot::Query

self



157
158
159
160
# File 'lib/sunspot/query.rb', line 157

def build(&block)
  Util.instance_eval_or_call(dsl, &block)
  self
end

#dslObject

Get a DSL instance for building this query.

Returns

Sunspot::DSL::Query

DSL instance



218
219
220
# File 'lib/sunspot/query.rb', line 218

def dsl #:nodoc:
  @dsl ||= DSL::Query.new(self)
end

#dynamic_field(field_name) ⇒ Object



242
243
244
# File 'lib/sunspot/query.rb', line 242

def dynamic_field(field_name)
  field = dynamic_fields_hash[field_name.to_sym] || raise(UnrecognizedFieldError, "No dynamic field configured for #{@types * ', '} with name #{field_name.inspect}")
end

#dynamic_query(base_name) ⇒ Object

Generate a DynamicQuery instance for the given base name. This gives you access to a subset of the Query API but the operations apply to dynamic fields inside the dynamic field definition specified by base_name.

Parameters

base_name<Symbol>

Base name of the dynamic field definition to use in the dynamic query operations

Returns

DynamicQuery

Instance providing dynamic query functionality for the given field definitions.



108
109
110
# File 'lib/sunspot/query.rb', line 108

def dynamic_query(base_name)
  DynamicQuery.new(dynamic_field(base_name), self)
end

#exclude_instance(instance) ⇒ Object

Exclude a particular instance from the search results

Parameters

instance<Object>

instance to exclude from results



75
76
77
# File 'lib/sunspot/query.rb', line 75

def exclude_instance(instance)
  @components << Restriction::SameAs.new(instance, true)
end

#field(field_name) ⇒ Object

Get a Sunspot::Field::Base instance corresponding to the given field name

Parameters

field_name<Symbol>

The field name for which to find a field

Returns

Sunspot::Field::Base

The field object corresponding to the given name

Raises

ArgumentError

If the given field name is not configured for the types being queried



238
239
240
# File 'lib/sunspot/query.rb', line 238

def field(field_name) #:nodoc:
  fields_hash[field_name.to_sym] || raise(UnrecognizedFieldError, "No field configured for #{@types * ', '} with name '#{field_name}'")
end

#options=(options) ⇒ Object

Pass in search options as a hash. This is not the preferred way of building a Sunspot search, but it is made available as experience shows Ruby developers like to pass in hashes. Probably nice for quick one-offs on the console, anyway.

Options (options)

:keywords

Keyword string for fulltext search

:conditions

Hash of key-value pairs, where keys are field names, and values are one of scalar, Array, or Range. Scalars are evaluated as EqualTo restrictions; Arrays are AnyOf restrictions, and Ranges are Between restrictions.

:order

Order the search results. Either a string or array of strings of the form “field_name direction”

:page

Page to use for pagination

:per_page

Number of results to show per page



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/sunspot/query.rb', line 268

def options=(options) #:nodoc:
  if options.has_key?(:keywords)
    self.keywords = options[:keywords]
  end
  if options.has_key?(:conditions)
    options[:conditions].each_pair do |field_name, value|
      begin
        restriction_type =
          case value
          when Array
            Restriction::AnyOf
          when Range
            Restriction::Between
          else
            Restriction::EqualTo
          end
        add_restriction(field_name, restriction_type, value)
      rescue UnrecognizedFieldError
        # ignore fields we don't recognize
      end
    end
  end
  if options.has_key?(:order)
    for order in Array(options[:order])
      order_by(*order.split(' '))
    end
  end
  if options.has_key?(:page)
    paginate(options[:page], options[:per_page])
  end
end

#order_by(field_name, direction = nil) ⇒ Object

Set result ordering.

Parameters

field_name<Symbol>

Name of the field on which to order

direction<Symbol>

:asc or :desc (default :asc)



146
147
148
# File 'lib/sunspot/query.rb', line 146

def order_by(field_name, direction = nil)
  @components << Sort.new(field(field_name), direction)
end

#pageObject

Page that this query will return (used by Sunspot::Search to expose pagination)

Returns

Integer

Page number



195
196
197
# File 'lib/sunspot/query.rb', line 195

def page #:nodoc:
  @pagination.page
end

#paginate(page, per_page = nil) ⇒ Object

Sets @start and @rows instance variables using pagination semantics

Parameters

page<Integer>

Page on which to start

per_page<Integer>

How many rows to display per page. Default taken from Sunspot.config.pagination.default_per_page



134
135
136
# File 'lib/sunspot/query.rb', line 134

def paginate(page, per_page = nil)
  @pagination.page, @pagination.per_page = page, per_page
end

#per_pageObject

Number of rows per page that this query will return (used by Sunspot::Search to expose pagination)

Returns

Integer

Rows per page



207
208
209
# File 'lib/sunspot/query.rb', line 207

def per_page #:nodoc:
  @pagination.per_page
end

#to_paramsObject

Representation of this query as solr-ruby parameters. Constructs the hash by deep-merging scope and facet parameters, adding in various other parameters from instance data.

Note that solr-ruby takes the :q parameter as a separate argument; for the sake of consistency, the Query object ignores this fact (the Search object extracts it back out).

Returns

Hash

Representation of query in solr-ruby form



175
176
177
178
179
180
181
182
183
184
185
# File 'lib/sunspot/query.rb', line 175

def to_params #:nodoc:
  params = {}
  query_components = []
  query_components << @keywords if @keywords
  query_components << types_phrase if types_phrase
  params[:q] = query_components.map { |component| "(#{component})"} * ' AND '
  for component in @components
    Util.deep_merge!(params, component.to_params)
  end
  params
end