Module: Blacklight::SolrHelper
- Included in:
- AssetsController, CatalogController, CatalogHelper, FileAssetsController, FolderController, GenericContentObjectsController
- Defined in:
- vendor/plugins/blacklight/lib/blacklight/solr_helper.rb
Overview
SolrHelper is a controller layer mixin. It is in the controller scope: request params, session etc.
NOTE: Be careful when creating variables here as they may be overriding something that already exists. The ActionController docs: api.rubyonrails.org/classes/ActionController/Base.html
Override these methods in your own controller for customizations:
class CatalogController < ActionController::Base
include Blacklight::SolrHelper def solr_search_params super.merge :per_page=>10 end
end
Defined Under Namespace
Classes: InvalidSolrID
Constant Summary
- MaxPerPage =
100
Class Method Summary (collapse)
Instance Method Summary (collapse)
-
- (Object) facet_limit_for(facet_field)
Look up facet limit for given facet_field.
-
- (Object) facet_limit_hash
Returns complete hash of key=facet_field, value=limit.
-
- (Object) get_facet_pagination(facet_field, extra_controller_params = {})
a solr query method used to paginate through a single facet field’s values /catalog/facet/language_facet.
-
- (Object) get_opensearch_response(field = nil, extra_controller_params = {})
a solr query method does a standard search but returns a simplified object.
-
- (Object) get_search_results(extra_controller_params = {})
a solr query method given a user query, return a solr response containing both result docs and facets
mixes in the Blacklight::Solr::SpellingSuggestions module.
-
- (Object) get_single_doc_via_search(extra_controller_params = {})
a solr query method this is used when selecting a search result: we have a query and a position in the search results and possibly some facets.
-
- (Object) get_solr_response_for_doc_id(id = nil, extra_controller_params = {})
a solr query method retrieve a solr document, given the doc id TODO: shouldn’t hardcode id field; should be setable to unique_key field in schema.xml.
-
- (Object) get_solr_response_for_field_values(field, values, extra_controller_params = {})
given a field name and array of values, get the matching SOLR documents.
- - (Object) max_per_page
-
- (Object) solr_doc_params(id = nil, extra_controller_params = {})
returns a params hash for finding a single solr document (CatalogController #show action) If the id arg is nil, then the value is fetched from params[:id] This method is primary called by the get_solr_response_for_doc_id method.
-
- (Object) solr_facet_params(facet_field, extra_controller_params = {})
returns a params hash for a single facet field solr query.
-
- (Object) solr_opensearch_params(field, extra_controller_params = {})
returns a solr params hash if field is nil, the value is fetched from Blacklight.config[:index][:show_link] the :fl (solr param) is set to the “field” value.
-
- (Object) solr_param_quote(val, options = {})
A helper method used for generating solr LocalParams, put quotes around the term unless it’s a bare-word.
-
- (Object) solr_search_params(extra_controller_params = {})
returns a params hash for searching solr.
Class Method Details
+ (Object) included(mod)
24 25 26 27 28 29 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 24 def self.included(mod) if mod.respond_to?(:helper_method) mod.helper_method(:facet_limit_hash) mod.helper_method(:facet_limit_for) end end |
Instance Method Details
- (Object) facet_limit_for(facet_field)
Look up facet limit for given facet_field. Will look at config, and if config is ‘true’ will look up from Solr @response if available. If no limit is avaialble, returns nil. Used from #solr_search_params to supply f.fieldname.facet.limit values in solr request (no @response available), and used in display (with @response available) to create a facet paginator with the right limit.
352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 352 def facet_limit_for(facet_field) limits_hash = facet_limit_hash return nil unless limits_hash limit = limits_hash[facet_field] if ( limit == true && @response && @response["responseHeader"] && @response["responseHeader"]["params"]) limit = @response["responseHeader"]["params"]["f.#{facet_field}.facet.limit"] || @response["responseHeader"]["params"]["facet.limit"] limit = (limit.to_i() -1) if limit limit = nil if limit == -2 # -1-1==-2, unlimited. elsif limit == true limit = nil end return limit end |
- (Object) facet_limit_hash
Returns complete hash of key=facet_field, value=limit. Used by SolrHelper#solr_search_params to add limits to solr request for all configured facet limits.
376 377 378 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 376 def facet_limit_hash Blacklight.config[:facet][:limits] end |
- (Object) get_facet_pagination(facet_field, extra_controller_params = {})
a solr query method used to paginate through a single facet field’s values /catalog/facet/language_facet
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 281 def get_facet_pagination(facet_field, extra_controller_params={}) solr_params = solr_facet_params(facet_field, extra_controller_params) # Make the solr call response = Blacklight.solr.find(solr_params) limit = if respond_to?(:facet_list_limit) facet_list_limit.to_s.to_i elsif solr_params[:"f.#{facet_field}.facet.limit"] solr_params[:"f.#{facet_field}.facet.limit"] - 1 else nil end # Actually create the paginator! # NOTE: The sniffing of the proper sort from the solr response is not # currently tested for, tricky to figure out how to test, since the # default setup we test against doesn't use this feature. return Blacklight::Solr::FacetPaginator.new(response.facets.first.items, :offset => solr_params['facet.offset'], :limit => limit, :sort => response["responseHeader"]["params"]["f.#{facet_field}.facet.sort"] || response["responseHeader"]["params"]["facet.sort"] ) end |
- (Object) get_opensearch_response(field = nil, extra_controller_params = {})
a solr query method does a standard search but returns a simplified object. an array is returned, the first item is the query string, the second item is an other array. This second array contains all of the field values for each of the documents… where the field is the “field” argument passed in.
337 338 339 340 341 342 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 337 def get_opensearch_response(field=nil, extra_controller_params={}) solr_params = solr_opensearch_params(extra_controller_params) response = Blacklight.solr.find(solr_params) a = [solr_params[:q]] a << response.docs.map {|doc| doc[solr_params[:fl]].to_s } end |
- (Object) get_search_results(extra_controller_params = {})
a solr query method given a user query, return a solr response containing both result docs and facets
mixes in the Blacklight::Solr::SpellingSuggestions module
the response will have a spelling_suggestions method
Returns a two-element array (aka duple) with first the solr response object, and second an array of SolrDocuments representing the response.docs
193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 193 def get_search_results(extra_controller_params={}) # In later versions of Rails, the #benchmark method can do timing # better for us. bench_start = Time.now solr_response = Blacklight.solr.find( self.solr_search_params(extra_controller_params) ) document_list = solr_response.docs.collect {|doc| SolrDocument.new(doc)} Rails.logger.debug("Solr fetch: #{self.class}#get_search_results (#{'%.1f' % ((Time.now.to_f - bench_start.to_f)*1000)}ms)") return [solr_response, document_list] end |
- (Object) get_single_doc_via_search(extra_controller_params = {})
a solr query method this is used when selecting a search result: we have a query and a position in the search results and possibly some facets
312 313 314 315 316 317 318 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 312 def get_single_doc_via_search(extra_controller_params={}) solr_params = solr_search_params(extra_controller_params) solr_params[:per_page] = 1 solr_params[:rows] = 1 solr_params[:fl] = '*' Blacklight.solr.find(solr_params).docs.first end |
- (Object) get_solr_response_for_doc_id(id = nil, extra_controller_params = {})
a solr query method retrieve a solr document, given the doc id TODO: shouldn’t hardcode id field; should be setable to unique_key field in schema.xml
223 224 225 226 227 228 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 223 def get_solr_response_for_doc_id(id=nil, extra_controller_params={}) solr_response = Blacklight.solr.find solr_doc_params(id, extra_controller_params) raise InvalidSolrID.new if solr_response.docs.empty? document = SolrDocument.new(solr_response.docs.first) [solr_response, document] end |
- (Object) get_solr_response_for_field_values(field, values, extra_controller_params = {})
given a field name and array of values, get the matching SOLR documents
231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 231 def get_solr_response_for_field_values(field, values, extra_controller_params={}) value_str = "(\"" + values.to_a.join("\" OR \"") + "\")" solr_params = { :qt => "standard", # need boolean for OR :q => "#{field}:#{value_str}", 'fl' => "*", 'facet' => 'false', 'spellcheck' => 'false' } solr_response = Blacklight.solr.find( self.solr_search_params(solr_params.merge(extra_controller_params)) ) document_list = solr_response.docs.collect{|doc| SolrDocument.new(doc) } [solr_response,document_list] end |
- (Object) max_per_page
380 381 382 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 380 def max_per_page MaxPerPage end |
- (Object) solr_doc_params(id = nil, extra_controller_params = {})
returns a params hash for finding a single solr document (CatalogController #show action) If the id arg is nil, then the value is fetched from params[:id] This method is primary called by the get_solr_response_for_doc_id method.
211 212 213 214 215 216 217 218 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 211 def solr_doc_params(id=nil, extra_controller_params={}) id ||= params[:id] # just to be consistent with the other solr param methods: { :qt => :document, :id => id }.deep_merge(extra_controller_params.symbolize_keys) end |
- (Object) solr_facet_params(facet_field, extra_controller_params = {})
returns a params hash for a single facet field solr query. used primary by the get_facet_pagination method. Looks up Facet Paginator request params from current request params to figure out sort and offset. Default limit for facet list can be specified by defining a controller method facet_list_limit, otherwise 20.
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 251 def solr_facet_params(facet_field, extra_controller_params={}) input = params.deep_merge(extra_controller_params) # First start with a standard solr search params calculations, # for any search context in our request params. solr_params = solr_search_params(extra_controller_params) # Now override with our specific things for fetching facet values solr_params[:"facet.field"] = facet_field # Need to set as f.facet_field.facet.limit to make sure we # override any field-specific default in the solr request handler. solr_params[:"f.#{facet_field}.facet.limit"] = if solr_params["facet.limit"] solr_params["facet.limit"] + 1 elsif respond_to?(:facet_list_limit) facet_list_limit.to_s.to_i + 1 else 20 + 1 end solr_params['facet.offset'] = input[ Blacklight::Solr::FacetPaginator.request_keys[:offset] ].to_i # will default to 0 if nil solr_params['facet.sort'] = input[ Blacklight::Solr::FacetPaginator.request_keys[:sort] ] solr_params[:rows] = 0 return solr_params end |
- (Object) solr_opensearch_params(field, extra_controller_params = {})
returns a solr params hash if field is nil, the value is fetched from Blacklight.config[:index][:show_link] the :fl (solr param) is set to the “field” value. per_page is set to 10
324 325 326 327 328 329 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 324 def solr_opensearch_params(field, extra_controller_params={}) solr_params = solr_search_params(extra_controller_params) solr_params[:per_page] = 10 solr_params[:fl] = Blacklight.config[:index][:show_link] solr_params end |
- (Object) solr_param_quote(val, options = {})
A helper method used for generating solr LocalParams, put quotes around the term unless it’s a bare-word. Escape internal quotes if needed.
33 34 35 36 37 38 39 40 41 42 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 33 def solr_param_quote(val, = {}) [:quote] ||= '"' unless val =~ /^[a-zA-Z$_\-\^]+$/ val = [:quote] + # Yes, we need crazy escaping here, to deal with regexp esc too! val.gsub("'", "\\\\\'").gsub('"', "\\\\\"") + [:quote] end return val end |
- (Object) solr_search_params(extra_controller_params = {})
returns a params hash for searching solr. The CatalogController #index action uses this. Solr parameters can come from a number of places. From lowest precedence to highest:
1. General defaults in blacklight config (are trumped by) 2. defaults for the particular search field identified by params[:search_field] (are trumped by) 3. certain parameters directly on input HTTP query params * not just any parameter is grabbed willy nilly, only certain ones are allowed by HTTP input) * for legacy reasons, qt in http query does not over-ride qt in search field definition default. 4. extra parameters passed in as argument.
spellcheck.q will be supplied with the [:q] value unless specifically specified otherwise.
Incoming parameter :f is mapped to :fq solr parameter.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'vendor/plugins/blacklight/lib/blacklight/solr_helper.rb', line 59 def solr_search_params(extra_controller_params={}) solr_parameters = {} # Order of precedence for all the places solr params can come from, # start lowest, and keep over-riding with higher. #### # Start with general defaults from BL config. Need to use custom # merge to dup values, to avoid later mutating the original by mistake. if Blacklight.config[:default_solr_params] Blacklight.config[:default_solr_params].each_pair do |key, value| solr_parameters[key] = case value when Hash then value.dup when Array then value.dup else value end end end ### # Merge in search field configured values, if present, over-writing general # defaults ### search_field_def = Blacklight.search_field_def_for_key(params[:search_field] || extra_controller_params[:search_field]) solr_parameters[:qt] = search_field_def[:qt] if search_field_def if ( search_field_def && search_field_def[:solr_parameters]) solr_parameters.merge!( search_field_def[:solr_parameters]) end ### # Merge in certain values from HTTP query itelf ### # Omit empty strings and nil values. [:facets, :f, :page, :sort, :per_page].each do |key| solr_parameters[key] = params[key] unless params[key].blank? end # :q is meaningful as an empty string, should be used unless nil! [:q].each do |key| solr_parameters[key] = params[key] if params[key] end # pass through any facet fields from request params["facet.field"] to # solr params. Used by Stanford for it's "faux hierarchical facets". if params.has_key?("facet.field") solr_parameters[:"facet.field"] ||= [] solr_parameters[:"facet.field"].concat( [params["facet.field"]].flatten ).uniq! end # qt is handled different for legacy reasons; qt in HTTP param can not # over-ride qt from search_field_def defaults, it's only used if there # was no qt from search_field_def_defaults unless params[:qt].blank? || ( search_field_def && search_field_def[:qt]) solr_parameters[:qt] = params[:qt] end ### # Merge in any values from extra_params argument. It doesn't seem like # we should have to take a slice of just certain keys, but legacy code # seems to put arguments in here that aren't really expected to turn # into solr params. ### solr_parameters.deep_merge!(extra_controller_params.slice(:qt, :q, :facets, :page, :per_page, :phrase_filters, :f, :fq, :fl, :sort, :qf, :df ).symbolize_keys ) ### # Defaults for otherwise blank values and normalization. ### # TODO: Change calling code to expect this as a symbol instead of # a string, for consistency? :'spellcheck.q' is a symbol. Right now # callers assume a string. solr_parameters["spellcheck.q"] = solr_parameters[:q] unless solr_parameters["spellcheck.q"] # And fix the 'facets' parameter to be the way the solr expects it. solr_parameters[:facets]= {:fields => solr_parameters[:facets]} if solr_parameters[:facets] # :fq, map from :f. if ( solr_parameters[:f]) f_request_params = solr_parameters.delete(:f) solr_parameters[:fq] ||= [] f_request_params.each_pair do |facet_field, value_list| value_list.each do |value| solr_parameters[:fq] << "{!raw f=#{facet_field}}#{value}" end end end # Facet 'more' limits. Add +1 to any configured facets limits, facet_limit_hash.each_key do |field_name| next if field_name.nil? # skip the 'default' key next unless (limit = facet_limit_for(field_name)) solr_parameters[:"f.#{field_name}.facet.limit"] = (limit + 1) end ## # Merge in search-field-specified LocalParams into q param in # solr LocalParams syntax ## if (search_field_def && hash = search_field_def[:solr_local_parameters]) local_params = hash.collect do |key, val| key.to_s + "=" + solr_param_quote(val, :quote => "'") end.join(" ") solr_parameters[:q] = "{!#{local_params}} #{solr_parameters[:q]}" end ### # Sanity/requirements checks. ### # limit to MaxPerPage (100). Tests want this to be a string not an integer, # not sure why. solr_parameters[:per_page] = solr_parameters[:per_page].to_i > self.max_per_page ? self.max_per_page.to_s : solr_parameters[:per_page] return solr_parameters end |