Class: Sunspot::Search::AbstractSearch
- Inherits:
-
Object
- Object
- Sunspot::Search::AbstractSearch
- Defined in:
- lib/sunspot/search/abstract_search.rb
Overview
This class encapsulates the results of a Solr search. It provides access to search results, total result count, facets, and pagination information. Instances of Search are returned by the Sunspot.search and Sunspot.new_search methods.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#facets ⇒ Object
readonly
Retrieve all facet objects defined for this search, in order they were defined.
-
#query ⇒ Object
readonly
:nodoc:.
-
#request_handler ⇒ Object
Returns the value of attribute request_handler.
Instance Method Summary collapse
-
#add_date_facet(field, options) ⇒ Object
:nodoc:.
-
#add_field_facet(field, options = {}) ⇒ Object
:nodoc:.
-
#add_query_facet(name, options) ⇒ Object
:nodoc:.
-
#build(&block) ⇒ Object
Build this search using a DSL block.
-
#data_accessor_for(clazz) ⇒ Object
Get the data accessor that will be used to load a particular class out of persistent storage.
-
#dynamic_facet(base_name, dynamic_name) ⇒ Object
Deprecated in favor of optional second argument to #facet.
-
#each_hit_with_result ⇒ Object
Convenience method to iterate over hit and result objects.
-
#execute ⇒ Object
Execute the search on the Solr instance and store the results.
-
#execute! ⇒ Object
:nodoc: deprecated.
-
#facet(name, dynamic_name = nil) ⇒ Object
Get the facet object for the given name.
-
#facet_response ⇒ Object
:nodoc:.
-
#fq_response_header ⇒ Object
Decomposes the Solr “Filter Query” (fq) parameter array further into a hash that can be easily digested when constructing FieldFacet.rows.
-
#hits(options = {}) ⇒ Object
(also: #raw_results)
Access raw Solr result information.
-
#initialize(connection, setup, query, configuration) ⇒ AbstractSearch
constructor
:nodoc:.
-
#inspect ⇒ Object
:nodoc:.
-
#populate_hits ⇒ Object
Populate the Hit objects with their instances.
-
#results ⇒ Object
Get the collection of results as instantiated objects.
-
#total ⇒ Object
The total number of documents matching the query parameters.
Constructor Details
#initialize(connection, setup, query, configuration) ⇒ AbstractSearch
:nodoc:
21 22 23 24 25 26 |
# File 'lib/sunspot/search/abstract_search.rb', line 21 def initialize(connection, setup, query, configuration) #:nodoc: @connection, @setup, @query = connection, setup, query @query.paginate(1, configuration.pagination.default_per_page) @facets = [] @facets_by_name = {} end |
Instance Attribute Details
#facets ⇒ Object (readonly)
Retrieve all facet objects defined for this search, in order they were defined. To retrieve an individual facet by name, use #facet()
17 18 19 |
# File 'lib/sunspot/search/abstract_search.rb', line 17 def facets @facets end |
#query ⇒ Object (readonly)
:nodoc:
18 19 20 |
# File 'lib/sunspot/search/abstract_search.rb', line 18 def query @query end |
#request_handler ⇒ Object
Returns the value of attribute request_handler.
19 20 21 |
# File 'lib/sunspot/search/abstract_search.rb', line 19 def request_handler @request_handler end |
Instance Method Details
#add_date_facet(field, options) ⇒ Object
:nodoc:
287 288 289 290 |
# File 'lib/sunspot/search/abstract_search.rb', line 287 def add_date_facet(field, ) #:nodoc: name = ([:name] || field.name) add_facet(name, DateFacet.new(field, self, )) end |
#add_field_facet(field, options = {}) ⇒ Object
:nodoc:
278 279 280 281 |
# File 'lib/sunspot/search/abstract_search.rb', line 278 def add_field_facet(field, = {}) #:nodoc: name = ([:name] || field.name) add_facet(name, FieldFacet.new(field, self, )) end |
#add_query_facet(name, options) ⇒ Object
:nodoc:
283 284 285 |
# File 'lib/sunspot/search/abstract_search.rb', line 283 def add_query_facet(name, ) #:nodoc: add_facet(name, QueryFacet.new(name, self, )) end |
#build(&block) ⇒ Object
Build this search using a DSL block. This method can be called more than once on an unexecuted search (e.g., Sunspot.new_search) in order to build a search incrementally.
Example
search = Sunspot.new_search(Post)
search.build do
with(:published_at).less_than Time.now
end
search.execute
247 248 249 250 |
# File 'lib/sunspot/search/abstract_search.rb', line 247 def build(&block) Util.instance_eval_or_call(dsl, &block) self end |
#data_accessor_for(clazz) ⇒ Object
Get the data accessor that will be used to load a particular class out of persistent storage. Data accessors can implement any methods that may be useful for refining how data is loaded out of storage. When building a search manually (e.g., using the Sunspot#new_search method), this should be used before calling #execute(). Use the Sunspot::DSL::Search#data_accessor_for method when building searches using the block DSL.
229 230 231 232 |
# File 'lib/sunspot/search/abstract_search.rb', line 229 def data_accessor_for(clazz) #:nodoc: (@data_accessors ||= {})[clazz.name.to_sym] ||= Adapters::DataAccessor.create(clazz) end |
#dynamic_facet(base_name, dynamic_name) ⇒ Object
Deprecated in favor of optional second argument to #facet
174 175 176 |
# File 'lib/sunspot/search/abstract_search.rb', line 174 def dynamic_facet(base_name, dynamic_name) #:nodoc: facet(base_name, dynamic_name) end |
#each_hit_with_result ⇒ Object
Convenience method to iterate over hit and result objects. Block is yielded a Sunspot::Server::Hit instance and a Sunspot::Server::Result instance.
Note that this method iterates over verified hits (see #hits method for more information).
104 105 106 107 108 |
# File 'lib/sunspot/search/abstract_search.rb', line 104 def each_hit_with_result verified_hits.each do |hit| yield(hit, hit.result) end end |
#execute ⇒ Object
Execute the search on the Solr instance and store the results. If you use Sunspot#search() to construct your searches, there is no need to call this method as it has already been called. If you use Sunspot#new_search(), you will need to call this method after building the query.
35 36 37 38 39 40 |
# File 'lib/sunspot/search/abstract_search.rb', line 35 def execute reset params = @query.to_params @solr_result = @connection.post "#{request_handler}", :params => params, :headers => { 'Content-Type' => 'application/x-www-form-urlencoded' } self end |
#execute! ⇒ Object
:nodoc: deprecated
42 43 44 |
# File 'lib/sunspot/search/abstract_search.rb', line 42 def execute! #:nodoc: deprecated execute end |
#facet(name, dynamic_name = nil) ⇒ Object
Get the facet object for the given name. ‘name` can either be the name given to a query facet, or the field name of a field facet. Returns a Sunspot::Facet object.
Parameters
- name<Symbol>
-
Name of the field to return the facet for, or the name given to the query facet when the search was constructed.
- dynamic_name<Symbol>
-
If faceting on a dynamic field, this is the dynamic portion of the field name.
Example:
search = Sunspot.search(Post) do
facet :category_ids
dynamic :custom do
facet :cuisine
end
facet :age do
row 'Less than a month' do
with(:published_at).greater_than(1.month.ago)
end
row 'Less than a year' do
with(:published_at, 1.year.ago..1.month.ago)
end
row 'More than a year' do
with(:published_at).less_than(1.year.ago)
end
end
end
search.facet(:category_ids)
#=> Facet for :category_ids field
search.facet(:custom, :cuisine)
#=> Facet for the dynamic field :cuisine in the :custom field definition
search.facet(:age)
#=> Facet for the query facet named :age
161 162 163 164 165 166 167 168 169 |
# File 'lib/sunspot/search/abstract_search.rb', line 161 def facet(name, dynamic_name = nil) if name if dynamic_name @facets_by_name[:"#{name}:#{dynamic_name}"] else @facets_by_name[name.to_sym] end end end |
#facet_response ⇒ Object
:nodoc:
178 179 180 |
# File 'lib/sunspot/search/abstract_search.rb', line 178 def facet_response #:nodoc: @solr_result['facet_counts'] end |
#fq_response_header ⇒ Object
Decomposes the Solr “Filter Query” (fq) parameter array further into a hash that can be easily digested when constructing FieldFacet.rows. Specifically, it is used to add a boolean “selected” attribute on each row so it’s easy to pick out which of the facets returned in a result are part of the originating query. This is useful for doing something like generating “undo” links, or showing checkbox initial state as checked.
Filter query values with keys ending in ‘_im’ and ‘_s’ are processed into their constituent parts.
solr_response_header[‘fq’] is an array of strings of the form, for example: fq: [“type:Package”,
"amenities_ids_im:(9 AND 12)",
"neighborhood_s:(East\ Village OR Chelsea)",
"capacity_max_is:[30 TO *]"
]
which is converted to the equivalent hash: fq_response_header: [“type” => “Package”,
"amenties_ids_im" => ["9", "12"],
"neighborhood_s" => ["East Village", "Chelsea"],
"capacity_max_is" => "[30 TO *]"
]
205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/sunspot/search/abstract_search.rb', line 205 def fq_response_header @fq_response_header ||= begin h = Hash.new solr_response_header['params']['fq'].each do |filter_query| field, value = filter_query.split(':') field = field.gsub(/^\{\!tag=.*?\}/, '') # strip exclude tags value = value.gsub(/^\(|\)$|\\/, '') # strips surrounding parens and \, value = value.split(/ AND | OR /) if facet_split[0] =~ /_im$|_s$/ h[field] = value end h end end |
#hits(options = {}) ⇒ Object Also known as: raw_results
Access raw Solr result information. Returns a collection of Hit objects that contain the class name, primary key, keyword relevance score (if applicable), and any stored fields.
Options (options)
- :verify
-
Only return hits that reference objects that actually exist in the data store. This causes results to be eager-loaded from the data store, unlike the normal behavior of this method, which only loads the referenced results when Hit#result is first called.
Returns
- Array
-
Ordered collection of Hit objects
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/sunspot/search/abstract_search.rb', line 79 def hits( = {}) if [:verify] verified_hits else @hits ||= begin hits = if solr_response && solr_response['docs'] solr_response['docs'].map do |doc| Hit.new(doc, highlights_for(doc), self) end end paginate_collection(hits || []) end end end |
#inspect ⇒ Object
:nodoc:
274 275 276 |
# File 'lib/sunspot/search/abstract_search.rb', line 274 def inspect #:nodoc: "<Sunspot::Search:#{query.to_params.inspect}>" end |
#populate_hits ⇒ Object
Populate the Hit objects with their instances. This is invoked the first time any hit has its instance requested, and all hits are loaded as a batch.
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/sunspot/search/abstract_search.rb', line 257 def populate_hits #:nodoc: id_hit_hash = Hash.new { |h, k| h[k] = {} } hits.each do |hit| id_hit_hash[hit.class_name][hit.primary_key] = hit end id_hit_hash.each_pair do |class_name, hits| ids = hits.map { |id, hit| hit.primary_key } data_accessor = data_accessor_for(Util.full_const_get(class_name)) hits_for_class = id_hit_hash[class_name] data_accessor.load_all(ids).each do |result| hit = hits_for_class.delete(Adapters::InstanceAdapter.adapt(result).id.to_s) hit.result = result end hits_for_class.values.each { |hit| hit.result = nil } end end |
#results ⇒ Object
Get the collection of results as instantiated objects. If WillPaginate is available, the results will be a WillPaginate::Collection instance; if not, it will be a vanilla Array.
If not all of the results referenced by the Solr hits actually exist in the data store, Sunspot will only return the results that do exist.
Returns
- WillPaginate::Collection or Array
-
Instantiated result objects
58 59 60 |
# File 'lib/sunspot/search/abstract_search.rb', line 58 def results @results ||= paginate_collection(verified_hits.map { |hit| hit.instance }) end |
#total ⇒ Object
The total number of documents matching the query parameters
Returns
- Integer
-
Total matching documents
117 118 119 |
# File 'lib/sunspot/search/abstract_search.rb', line 117 def total @total ||= solr_response['numFound'] || 0 end |