Module: Blacklight::Solr::SearchBuilderBehavior
- Extended by:
- ActiveSupport::Concern
- Included in:
- SearchBuilder
- Defined in:
- lib/blacklight/solr/search_builder_behavior.rb
Overview
This depends on being imported into a class that extends AbstractSearchBuilder
Instance Method Summary collapse
- #add_additional_filters(solr_parameters, additional_filters = nil) ⇒ Object
-
#add_adv_search_clauses(solr_parameters) ⇒ Object
Transform “clause” parameters into the Solr JSON Query DSL.
-
#add_facet_fq_to_solr(solr_parameters) ⇒ Object
Add any existing facet limits, stored in app-level HTTP query as :f, to solr as appropriate :fq query.
- #add_facet_paging_to_solr(solr_params) ⇒ Object
- #add_facet_suggestion_parameters(solr_params) ⇒ Object
-
#add_facets_for_advanced_search_form(solr_parameters) ⇒ Hash
Merge the advanced search form parameters into the solr parameters.
-
#add_facetting_to_solr(solr_parameters) ⇒ Object
Add appropriate Solr facetting directives in, including taking account of our facet paging/‘more’.
-
#add_group_config_to_solr(solr_parameters) ⇒ Object
Remove the group parameter if we’ve faceted on the group field (e.g. for the full results for a group).
-
#add_paging_to_solr(solr_params) ⇒ Object
copy paging params from BL app over to solr, changing app level per_page and page to Solr rows and start.
-
#add_query_to_solr(solr_parameters) ⇒ Object
Take the user-entered query, and put it in the solr params, including config’s “search field” params for current search field.
- #add_search_field_default_parameters(solr_parameters) ⇒ Object
- #add_search_field_with_json_query_parameters(solr_parameters) ⇒ Object
- #add_solr_facet_json_params(solr_parameters, field_name, facet, **additional_parameters) ⇒ Object
- #add_solr_fields_to_query(solr_parameters) ⇒ Object
-
#add_sorting_to_solr(solr_parameters) ⇒ Object
copy sorting params from BL app over to solr.
-
#adv_search_clause(clause, default_op) ⇒ Array
The first element is the query operator and the second is the value to add.
-
#default_solr_parameters(solr_parameters) ⇒ Object
Start with general defaults from BL config.
-
#facet_limit_for(facet_field) ⇒ Object
Look up facet limit for given facet_field.
-
#facet_limit_with_pagination(field_name) ⇒ Object
Support facet paging and ‘more’ links, by sending a facet.limit one more than what we want to page at, according to configured facet limits.
-
#solr_param_quote(val, options = {}) ⇒ Object
A helper method used for generating solr LocalParams, put quotes around the term unless it’s a bare-word.
- #with_ex_local_param(ex, value) ⇒ Object
Instance Method Details
#add_additional_filters(solr_parameters, additional_filters = nil) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 74 def add_additional_filters(solr_parameters, additional_filters = nil) q = additional_filters || @additional_filters return if q.blank? if q.values.any?(&:blank?) # if any field parameters are empty, exclude _all_ results solr_parameters.append_query "{!lucene}NOT *:*" else composed_query = q.map do |field, values| "#{field}:(#{Array(values).map { |x| solr_param_quote(x) }.join(' OR ')})" end.join(" AND ") solr_parameters.append_query "{!lucene}#{composed_query}" end solr_parameters[:defType] = 'lucene' solr_parameters[:spellcheck] = 'false' end |
#add_adv_search_clauses(solr_parameters) ⇒ Object
Transform “clause” parameters into the Solr JSON Query DSL
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 104 def add_adv_search_clauses(solr_parameters) return if search_state.clause_params.blank? # We need to specify lucene as the top-level defType when using JSON Query DSL in Solr versions # between 7.2.0 & 9.4.0. After 9.4.0 this is no longer necessary, but also not harmful to include. solr_parameters[:defType] = 'lucene' # Disable spellcheck, which doesn't work when using JSON Query DSL solr_parameters[:spellcheck] = 'false' defaults = { must: [], must_not: [], should: [] } default_op = blacklight_params[:op]&.to_sym || :must solr_parameters[:mm] = 1 if default_op == :should && search_state.clause_params.values.any? { |clause| } search_state.clause_params.each_value do |clause| op, query = adv_search_clause(clause, default_op) next unless defaults.key?(op) solr_parameters.append_boolean_query(op, query) end end |
#add_facet_fq_to_solr(solr_parameters) ⇒ Object
Add any existing facet limits, stored in app-level HTTP query as :f, to solr as appropriate :fq query.
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 149 def add_facet_fq_to_solr(solr_parameters) # convert a String value into an Array if solr_parameters[:fq].is_a? String solr_parameters[:fq] = [solr_parameters[:fq]] end search_state.filters.each do |filter| filter_query_builder_class_or_proc = filter.config.filter_query_builder || DefaultFilterQueryBuilder if filter_query_builder_class_or_proc.is_a?(Class) filter_query_builder = filter_query_builder_class_or_proc.new(blacklight_config: blacklight_config) filter_query, subqueries = filter_query_builder.call(filter, solr_parameters) else # TODO: Maybe deprecate proc? filter_query, subqueries = filter_query_builder_class_or_proc.call(self, filter, solr_parameters) end Array(filter_query).each do |fq| solr_parameters.append_filter_query(fq) end solr_parameters.merge!(subqueries) if subqueries end end |
#add_facet_paging_to_solr(solr_params) ⇒ Object
260 261 262 263 264 265 266 267 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 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 260 def add_facet_paging_to_solr(solr_params) return if facet.blank? facet_config = blacklight_config.facet_fields[facet] solr_params[:rows] = 0 limit = if solr_params["facet.limit"] solr_params["facet.limit"].to_i else facet_config.fetch(:more_limit, blacklight_config.default_more_limit) end page = search_state.facet_page sort = search_state.facet_sort prefix = search_state.facet_prefix offset = (page - 1) * limit if facet_config.json add_solr_facet_json_params(solr_parameters, facet, facet_config, limit: limit + 1, offset: offset, sort: sort, prefix: prefix) return end # Now override with our specific things for fetching facet values facet_ex = facet_config.respond_to?(:ex) ? facet_config.ex : nil solr_params[:'facet.field'] = with_ex_local_param(facet_ex, facet_config.field) # Need to set as f.facet_field.facet.* to make sure we # override any field-specific default in the solr request handler. solr_params[:"f.#{facet_config.field}.facet.limit"] = limit + 1 solr_params[:"f.#{facet_config.field}.facet.offset"] = offset solr_params[:"f.#{facet_config.field}.facet.sort"] = sort if sort solr_params[:"f.#{facet_config.field}.facet.prefix"] = prefix if prefix end |
#add_facet_suggestion_parameters(solr_params) ⇒ Object
295 296 297 298 299 300 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 295 def add_facet_suggestion_parameters(solr_params) return if facet.blank? || facet_suggestion_query.blank? solr_params[:'facet.contains'] = facet_suggestion_query[0..50] solr_params[:'facet.contains.ignoreCase'] = true end |
#add_facets_for_advanced_search_form(solr_parameters) ⇒ Hash
Merge the advanced search form parameters into the solr parameters
139 140 141 142 143 144 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 139 def add_facets_for_advanced_search_form(solr_parameters) return unless search_state.controller&.action_name == 'advanced_search' && blacklight_config.advanced_search[:form_solr_parameters] solr_parameters.merge!(blacklight_config.advanced_search[:form_solr_parameters]) end |
#add_facetting_to_solr(solr_parameters) ⇒ Object
Add appropriate Solr facetting directives in, including taking account of our facet paging/‘more’. This is not about solr ‘fq’, this is about solr facet.* params.
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 191 def add_facetting_to_solr(solr_parameters) facet_fields_to_include_in_request.each do |field_name, facet| solr_parameters[:facet] ||= true if facet.json add_solr_facet_json_params(solr_parameters, field_name, facet) next end if facet.pivot solr_parameters.append_facet_pivot with_ex_local_param(facet.ex, facet.pivot.join(",")) elsif facet.query solr_parameters.append_facet_query facet.query.values.map { |x| with_ex_local_param(facet.ex, x[:fq]) } else solr_parameters.append_facet_fields with_ex_local_param(facet.ex, facet.field) end if facet.sort solr_parameters[:"f.#{facet.field}.facet.sort"] = facet.sort end facet.solr_params&.each do |k, v| solr_parameters[:"f.#{facet.field}.#{k}"] = v end limit = facet_limit_with_pagination(field_name) solr_parameters[:"f.#{facet.field}.facet.limit"] = limit if limit end end |
#add_group_config_to_solr(solr_parameters) ⇒ Object
Remove the group parameter if we’ve faceted on the group field (e.g. for the full results for a group)
256 257 258 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 256 def add_group_config_to_solr solr_parameters solr_parameters[:group] = false if search_state.filter(grouped_key_for_results).any? end |
#add_paging_to_solr(solr_params) ⇒ Object
copy paging params from BL app over to solr, changing app level per_page and page to Solr rows and start.
243 244 245 246 247 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 243 def add_paging_to_solr(solr_params) solr_params[:rows] = rows solr_params[:start] = start if start.nonzero? end |
#add_query_to_solr(solr_parameters) ⇒ Object
Take the user-entered query, and put it in the solr params, including config’s “search field” params for current search field. also include setting spellcheck.q.
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 57 def add_query_to_solr(solr_parameters) ## # Create Solr 'q' including the user-entered q, prefixed by any # solr LocalParams in config, using solr LocalParams syntax. # http://wiki.apache.org/solr/LocalParams ## if search_field&.query_builder.present? add_search_field_query_builder_params(solr_parameters) elsif search_field&.clause_params.present? add_search_field_with_json_query_parameters(solr_parameters) elsif search_field&.solr_local_parameters.present? add_search_field_with_local_parameters(solr_parameters) elsif !search_state&.query_param.is_a?(Hash) solr_parameters.append_query search_state.query_param end end |
#add_search_field_default_parameters(solr_parameters) ⇒ Object
42 43 44 45 46 47 48 49 50 51 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 42 def add_search_field_default_parameters(solr_parameters) ### # Merge in search field configured values, if present, over-writing general # defaults if search_field solr_parameters[:qt] = search_field.qt if search_field.qt solr_parameters.deep_merge!(search_field.solr_parameters) if search_field.solr_parameters end end |
#add_search_field_with_json_query_parameters(solr_parameters) ⇒ Object
94 95 96 97 98 99 100 101 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 94 def add_search_field_with_json_query_parameters(solr_parameters) return unless search_state.query_param bool_query = search_field.clause_params.transform_values { |v| v.merge(query: search_state.query_param) } solr_parameters["spellcheck.q"] ||= search_state.query_param solr_parameters.append_boolean_query(:must, bool_query) end |
#add_solr_facet_json_params(solr_parameters, field_name, facet, **additional_parameters) ⇒ Object
172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 172 def add_solr_facet_json_params(solr_parameters, field_name, facet, **additional_parameters) solr_parameters[:json] ||= { facet: {} } solr_parameters[:json][:facet] ||= {} field_config = facet.json.respond_to?(:reverse_merge) ? facet.json : {} field_config = field_config.reverse_merge( type: 'terms', field: facet.field, limit: facet_limit_with_pagination(field_name) ).merge(additional_parameters) solr_parameters[:json][:facet][field_name] = field_config.compact_blank end |
#add_solr_fields_to_query(solr_parameters) ⇒ Object
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 221 def add_solr_fields_to_query solr_parameters blacklight_config.show_fields.select(&method(:should_add_field_to_request?)).each_value do |field| field.solr_params&.each do |k, v| solr_parameters[:"f.#{field.field}.#{k}"] = v end end blacklight_config.index_fields.select(&method(:should_add_field_to_request?)).each_value do |field| if field.highlight solr_parameters[:hl] = true solr_parameters.append_highlight_field field.field end field.solr_params&.each do |k, v| solr_parameters[:"f.#{field.field}.#{k}"] = v end end end |
#add_sorting_to_solr(solr_parameters) ⇒ Object
copy sorting params from BL app over to solr
251 252 253 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 251 def add_sorting_to_solr(solr_parameters) solr_parameters[:sort] = sort if sort.present? end |
#adv_search_clause(clause, default_op) ⇒ Array
Returns the first element is the query operator and the second is the value to add.
127 128 129 130 131 132 133 134 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 127 def adv_search_clause(clause, default_op) op = clause[:op]&.to_sym || default_op field = (blacklight_config.search_fields || {})[clause[:field]] if clause[:field] return unless field&.clause_params && clause[:query].present? [op, field.clause_params.transform_values { |v| v.merge(query: clause[:query]) }] end |
#default_solr_parameters(solr_parameters) ⇒ Object
Start with general defaults from BL config. Need to use custom merge to dup values, to avoid later mutating the original by mistake.
30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 30 def default_solr_parameters(solr_parameters) blacklight_config.default_solr_params.each do |key, value| solr_parameters[key] ||= if value.respond_to? :deep_dup value.deep_dup elsif value.respond_to?(:dup) && value.duplicable? value.dup else value end end end |
#facet_limit_for(facet_field) ⇒ Object
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 available, returns nil. Used from #add_facetting_to_solr 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.
316 317 318 319 320 321 322 323 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 316 def facet_limit_for(facet_field) facet = blacklight_config.facet_fields[facet_field] return if facet.blank? if facet.limit facet.limit == true ? blacklight_config.default_facet_limit : facet.limit end end |
#facet_limit_with_pagination(field_name) ⇒ Object
Support facet paging and ‘more’ links, by sending a facet.limit one more than what we want to page at, according to configured facet limits.
328 329 330 331 332 333 334 335 336 337 338 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 328 def facet_limit_with_pagination(field_name) limit = facet_limit_for(field_name) return if limit.nil? if limit > 0 limit + 1 else limit end end |
#solr_param_quote(val, options = {}) ⇒ Object
A helper method used for generating solr LocalParams, put quotes around the term unless it’s a bare-word. Escape internal quotes if needed.
344 345 346 347 348 349 350 351 352 353 354 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 344 def solr_param_quote(val, = {}) val = val.to_s [:quote] ||= '"' unless val =~ /^[a-zA-Z0-9$_\-\^]+$/ val = [:quote] + # Yes, we need crazy escaping here, to deal with regexp esc too! val.gsub("'", "\\\\'").gsub('"', "\\\\\"") + [:quote] end val end |
#with_ex_local_param(ex, value) ⇒ Object
302 303 304 305 306 307 308 |
# File 'lib/blacklight/solr/search_builder_behavior.rb', line 302 def with_ex_local_param(ex, value) if ex "{!ex=#{ex}}#{value}" else value end end |