blacklight 5.11.3 → 5.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/app/helpers/blacklight/blacklight_helper_behavior.rb +2 -2
- data/app/helpers/blacklight/catalog_helper_behavior.rb +2 -4
- data/app/helpers/blacklight/facets_helper_behavior.rb +10 -6
- data/app/helpers/blacklight/url_helper_behavior.rb +1 -1
- data/app/views/bookmarks/_clear_bookmarks_widget.html.erb +1 -0
- data/app/views/bookmarks/index.html.erb +0 -1
- data/blacklight.gemspec +1 -1
- data/config/locales/blacklight.en.yml +1 -0
- data/lib/blacklight.rb +2 -1
- data/lib/blacklight/bookmarks.rb +2 -0
- data/lib/blacklight/catalog.rb +1 -1
- data/lib/blacklight/configuration.rb +8 -1
- data/lib/blacklight/configuration/fields.rb +20 -10
- data/lib/blacklight/document.rb +43 -13
- data/lib/blacklight/document_presenter.rb +8 -4
- data/lib/blacklight/facet.rb +6 -54
- data/lib/blacklight/request_builders.rb +2 -2
- data/lib/blacklight/search_builder.rb +48 -18
- data/lib/blacklight/search_helper.rb +10 -10
- data/lib/blacklight/solr.rb +1 -1
- data/lib/blacklight/solr/search_builder.rb +2 -265
- data/lib/blacklight/solr/search_builder_behavior.rb +274 -0
- data/lib/blacklight/solr_repository.rb +1 -1
- data/lib/blacklight/solr_response.rb +8 -16
- data/lib/blacklight/solr_response/facets.rb +133 -25
- data/lib/blacklight/solr_response/group_response.rb +1 -1
- data/lib/blacklight/solr_response/pagination_methods.rb +0 -17
- data/lib/generators/blacklight/install_generator.rb +6 -1
- data/lib/generators/blacklight/search_builder_generator.rb +20 -0
- data/lib/generators/blacklight/templates/search_builder.rb +3 -0
- data/lib/railties/blacklight.rake +1 -1
- data/spec/controllers/catalog_controller_spec.rb +9 -9
- data/spec/helpers/blacklight_helper_spec.rb +29 -179
- data/spec/helpers/facets_helper_spec.rb +37 -75
- data/spec/helpers/url_helper_spec.rb +1 -1
- data/spec/lib/blacklight/configuration_spec.rb +18 -1
- data/spec/lib/blacklight/document_spec.rb +62 -0
- data/spec/lib/blacklight/search_builder_spec.rb +15 -13
- data/spec/lib/blacklight/search_helper_spec.rb +15 -16
- data/spec/lib/blacklight/solr/document_spec.rb +5 -3
- data/spec/lib/blacklight/solr/search_builder_spec.rb +0 -5
- data/spec/lib/blacklight/solr_response/facets_spec.rb +144 -10
- data/spec/lib/blacklight/solr_response_spec.rb +5 -13
- data/spec/lib/document_presenter_spec.rb +23 -27
- data/spec/views/catalog/_facets.html.erb_spec.rb +1 -1
- data/spec/views/catalog/_index_default.erb_spec.rb +2 -13
- data/spec/views/catalog/_show_default.erb_spec.rb +1 -13
- metadata +10 -4
@@ -98,8 +98,11 @@ module Blacklight::SearchHelper
|
|
98
98
|
# @param [List<Symbol] processor_chain a list of filter methods to run
|
99
99
|
# @return [Blacklight::SolrResponse] the solr response object
|
100
100
|
def search_results(user_params, search_params_logic)
|
101
|
-
|
102
|
-
|
101
|
+
builder = search_builder(search_params_logic).with(user_params)
|
102
|
+
builder.page(user_params[:page]) if user_params[:page]
|
103
|
+
builder.rows(user_params[:per_page] || user_params[:rows]) if user_params[:per_page] or user_params[:rows]
|
104
|
+
|
105
|
+
response = repository.search(builder.query)
|
103
106
|
|
104
107
|
case
|
105
108
|
when (response.grouped? && grouped_key_for_results)
|
@@ -173,7 +176,7 @@ module Blacklight::SearchHelper
|
|
173
176
|
# NOTE: The sniffing of the proper sort from the solr response is not
|
174
177
|
# currently tested for, tricky to figure out how to test, since the
|
175
178
|
# default setup we test against doesn't use this feature.
|
176
|
-
Blacklight::Solr::FacetPaginator.new(response.
|
179
|
+
Blacklight::Solr::FacetPaginator.new(response.aggregations[facet_field].items,
|
177
180
|
:offset => response.params[:"f.#{facet_field}.facet.offset"],
|
178
181
|
:limit => limit,
|
179
182
|
:sort => response.params[:"f.#{facet_field}.facet.sort"] || response.params["facet.sort"]
|
@@ -188,12 +191,8 @@ module Blacklight::SearchHelper
|
|
188
191
|
# the Blacklight app-level request params that define the search.
|
189
192
|
# @return [Blacklight::SolrDocument, nil] the found document or nil if not found
|
190
193
|
def get_single_doc_via_search(index, request_params)
|
191
|
-
|
192
|
-
|
193
|
-
request_params[:start] = (index - 1) # start at 0 to get 1st doc, 1 to get 2nd.
|
194
|
-
request_params[:rows] = 1
|
195
|
-
request_params[:fl] = '*'
|
196
|
-
response = repository.search(request_params)
|
194
|
+
query = search_builder.with(request_params).start(index - 1).rows(1).query(fl: "*")
|
195
|
+
response = repository.search(query)
|
197
196
|
response.documents.first
|
198
197
|
end
|
199
198
|
deprecation_deprecate :get_single_doc_via_search
|
@@ -201,8 +200,9 @@ module Blacklight::SearchHelper
|
|
201
200
|
# Get the previous and next document from a search result
|
202
201
|
# @return [Blacklight::SolrResponse, Array<Blacklight::SolrDocument>] the solr response and a list of the first and last document
|
203
202
|
def get_previous_and_next_documents_for_search(index, request_params, extra_controller_params={})
|
203
|
+
p = previous_and_next_document_params(index)
|
204
204
|
|
205
|
-
query = search_builder.with(request_params).query(extra_controller_params.merge(
|
205
|
+
query = search_builder.with(request_params).start(p.delete(:start)).rows(p.delete(:rows)).query(extra_controller_params.merge(p))
|
206
206
|
response = repository.search(query)
|
207
207
|
|
208
208
|
document_list = response.documents
|
data/lib/blacklight/solr.rb
CHANGED
@@ -1,269 +1,6 @@
|
|
1
1
|
module Blacklight::Solr
|
2
|
+
# @deprecated
|
2
3
|
class SearchBuilder < Blacklight::SearchBuilder
|
3
|
-
|
4
|
-
self.default_processor_chain = [:default_solr_parameters, :add_query_to_solr, :add_facet_fq_to_solr, :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr, :add_sorting_to_solr, :add_group_config_to_solr ]
|
5
|
-
|
6
|
-
####
|
7
|
-
# Start with general defaults from BL config. Need to use custom
|
8
|
-
# merge to dup values, to avoid later mutating the original by mistake.
|
9
|
-
def default_solr_parameters(solr_parameters)
|
10
|
-
blacklight_config.default_solr_params.each do |key, value|
|
11
|
-
solr_parameters[key] = if value.respond_to? :deep_dup
|
12
|
-
value.deep_dup
|
13
|
-
elsif value.respond_to? :dup and value.duplicable?
|
14
|
-
value.dup
|
15
|
-
else
|
16
|
-
value
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
##
|
22
|
-
# Take the user-entered query, and put it in the solr params,
|
23
|
-
# including config's "search field" params for current search field.
|
24
|
-
# also include setting spellcheck.q.
|
25
|
-
def add_query_to_solr(solr_parameters)
|
26
|
-
###
|
27
|
-
# Merge in search field configured values, if present, over-writing general
|
28
|
-
# defaults
|
29
|
-
###
|
30
|
-
# legacy behavior of user param :qt is passed through, but over-ridden
|
31
|
-
# by actual search field config if present. We might want to remove
|
32
|
-
# this legacy behavior at some point. It does not seem to be currently
|
33
|
-
# rspec'd.
|
34
|
-
solr_parameters[:qt] = blacklight_params[:qt] if blacklight_params[:qt]
|
35
|
-
|
36
|
-
if search_field
|
37
|
-
solr_parameters[:qt] = search_field.qt
|
38
|
-
solr_parameters.merge!( search_field.solr_parameters) if search_field.solr_parameters
|
39
|
-
end
|
40
|
-
|
41
|
-
##
|
42
|
-
# Create Solr 'q' including the user-entered q, prefixed by any
|
43
|
-
# solr LocalParams in config, using solr LocalParams syntax.
|
44
|
-
# http://wiki.apache.org/solr/LocalParams
|
45
|
-
##
|
46
|
-
if (search_field && hash = search_field.solr_local_parameters)
|
47
|
-
local_params = hash.collect do |key, val|
|
48
|
-
key.to_s + "=" + solr_param_quote(val, :quote => "'")
|
49
|
-
end.join(" ")
|
50
|
-
solr_parameters[:q] = "{!#{local_params}}#{blacklight_params[:q]}"
|
51
|
-
|
52
|
-
##
|
53
|
-
# Set Solr spellcheck.q to be original user-entered query, without
|
54
|
-
# our local params, otherwise it'll try and spellcheck the local
|
55
|
-
# params!
|
56
|
-
solr_parameters["spellcheck.q"] ||= blacklight_params[:q]
|
57
|
-
elsif blacklight_params[:q].is_a? Hash
|
58
|
-
q = blacklight_params[:q]
|
59
|
-
solr_parameters[:q] = if q.values.any?(&:blank?)
|
60
|
-
# if any field parameters are empty, exclude _all_ results
|
61
|
-
"{!lucene}NOT *:*"
|
62
|
-
else
|
63
|
-
"{!lucene}" + q.map do |field, values|
|
64
|
-
"#{field}:(#{ Array(values).map { |x| solr_param_quote(x) }.join(" OR ")})"
|
65
|
-
end.join(" AND ")
|
66
|
-
end
|
67
|
-
|
68
|
-
solr_parameters[:spellcheck] = 'false'
|
69
|
-
elsif blacklight_params[:q]
|
70
|
-
solr_parameters[:q] = blacklight_params[:q]
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
##
|
75
|
-
# Add any existing facet limits, stored in app-level HTTP query
|
76
|
-
# as :f, to solr as appropriate :fq query.
|
77
|
-
def add_facet_fq_to_solr(solr_parameters)
|
78
|
-
|
79
|
-
# convert a String value into an Array
|
80
|
-
if solr_parameters[:fq].is_a? String
|
81
|
-
solr_parameters[:fq] = [solr_parameters[:fq]]
|
82
|
-
end
|
83
|
-
|
84
|
-
# :fq, map from :f.
|
85
|
-
if ( blacklight_params[:f])
|
86
|
-
f_request_params = blacklight_params[:f]
|
87
|
-
|
88
|
-
f_request_params.each_pair do |facet_field, value_list|
|
89
|
-
Array(value_list).each do |value|
|
90
|
-
next if value.blank? # skip empty strings
|
91
|
-
solr_parameters.append_filter_query facet_value_to_fq_string(facet_field, value)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
##
|
98
|
-
# Add appropriate Solr facetting directives in, including
|
99
|
-
# taking account of our facet paging/'more'. This is not
|
100
|
-
# about solr 'fq', this is about solr facet.* params.
|
101
|
-
def add_facetting_to_solr(solr_parameters)
|
102
|
-
# While not used by BL core behavior, legacy behavior seemed to be
|
103
|
-
# to accept incoming params as "facet.field" or "facets", and add them
|
104
|
-
# on to any existing facet.field sent to Solr. Legacy behavior seemed
|
105
|
-
# to be accepting these incoming params as arrays (in Rails URL with []
|
106
|
-
# on end), or single values. At least one of these is used by
|
107
|
-
# Stanford for "faux hieararchial facets".
|
108
|
-
if blacklight_params.has_key?("facet.field") || blacklight_params.has_key?("facets")
|
109
|
-
solr_parameters[:"facet.field"].concat( [blacklight_params["facet.field"], blacklight_params["facets"]].flatten.compact ).uniq!
|
110
|
-
end
|
111
|
-
|
112
|
-
blacklight_config.facet_fields.select { |field_name,facet|
|
113
|
-
facet.include_in_request || (facet.include_in_request.nil? && blacklight_config.add_facet_fields_to_solr_request)
|
114
|
-
}.each do |field_name, facet|
|
115
|
-
solr_parameters[:facet] ||= true
|
116
|
-
|
117
|
-
case
|
118
|
-
when facet.pivot
|
119
|
-
solr_parameters.append_facet_pivot with_ex_local_param(facet.ex, facet.pivot.join(","))
|
120
|
-
when facet.query
|
121
|
-
solr_parameters.append_facet_query facet.query.map { |k, x| with_ex_local_param(facet.ex, x[:fq]) }
|
122
|
-
else
|
123
|
-
solr_parameters.append_facet_fields with_ex_local_param(facet.ex, facet.field)
|
124
|
-
end
|
125
|
-
|
126
|
-
if facet.sort
|
127
|
-
solr_parameters[:"f.#{facet.field}.facet.sort"] = facet.sort
|
128
|
-
end
|
129
|
-
|
130
|
-
if facet.solr_params
|
131
|
-
facet.solr_params.each do |k, v|
|
132
|
-
solr_parameters[:"f.#{facet.field}.#{k}"] = v
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
|
-
# Support facet paging and 'more'
|
137
|
-
# links, by sending a facet.limit one more than what we
|
138
|
-
# want to page at, according to configured facet limits.
|
139
|
-
solr_parameters[:"f.#{facet.field}.facet.limit"] = (facet_limit_for(field_name) + 1) if facet_limit_for(field_name)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
def add_solr_fields_to_query solr_parameters
|
144
|
-
blacklight_config.show_fields.select(&method(:should_add_field_to_request?)).each do |field_name, field|
|
145
|
-
if field.solr_params
|
146
|
-
field.solr_params.each do |k, v|
|
147
|
-
solr_parameters[:"f.#{field.field}.#{k}"] = v
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
blacklight_config.index_fields.select(&method(:should_add_field_to_request?)).each do |field_name, field|
|
153
|
-
if field.highlight
|
154
|
-
solr_parameters[:hl] = true
|
155
|
-
solr_parameters.append_highlight_field field.field
|
156
|
-
end
|
157
|
-
|
158
|
-
if field.solr_params
|
159
|
-
field.solr_params.each do |k, v|
|
160
|
-
solr_parameters[:"f.#{field.field}.#{k}"] = v
|
161
|
-
end
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
###
|
167
|
-
# copy paging params from BL app over to solr, changing
|
168
|
-
# app level per_page and page to Solr rows and start.
|
169
|
-
def add_paging_to_solr(solr_params)
|
170
|
-
# user-provided parameters should override any default row
|
171
|
-
solr_params[:rows] = rows(solr_params[:rows])
|
172
|
-
if page > 1
|
173
|
-
solr_params[:start] = solr_params[:rows].to_i * (page - 1)
|
174
|
-
end
|
175
|
-
end
|
176
|
-
|
177
|
-
###
|
178
|
-
# copy sorting params from BL app over to solr
|
179
|
-
def add_sorting_to_solr(solr_parameters)
|
180
|
-
solr_parameters[:sort] = sort unless sort.blank?
|
181
|
-
end
|
182
|
-
|
183
|
-
# Remove the group parameter if we've faceted on the group field (e.g. for the full results for a group)
|
184
|
-
def add_group_config_to_solr solr_parameters
|
185
|
-
if blacklight_params[:f] and blacklight_params[:f][grouped_key_for_results]
|
186
|
-
solr_parameters[:group] = false
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
|
-
def with_ex_local_param(ex, value)
|
191
|
-
if ex
|
192
|
-
"{!ex=#{ex}}#{value}"
|
193
|
-
else
|
194
|
-
value
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
# Look up facet limit for given facet_field. Will look at config, and
|
199
|
-
# if config is 'true' will look up from Solr @response if available. If
|
200
|
-
# no limit is avaialble, returns nil. Used from #add_facetting_to_solr
|
201
|
-
# to supply f.fieldname.facet.limit values in solr request (no @response
|
202
|
-
# available), and used in display (with @response available) to create
|
203
|
-
# a facet paginator with the right limit.
|
204
|
-
def facet_limit_for(facet_field)
|
205
|
-
facet = blacklight_config.facet_fields[facet_field]
|
206
|
-
return if facet.blank?
|
207
|
-
|
208
|
-
if facet.limit
|
209
|
-
facet.limit == true ? blacklight_config.default_facet_limit : facet.limit
|
210
|
-
end
|
211
|
-
end
|
212
|
-
|
213
|
-
##
|
214
|
-
# A helper method used for generating solr LocalParams, put quotes
|
215
|
-
# around the term unless it's a bare-word. Escape internal quotes
|
216
|
-
# if needed.
|
217
|
-
def solr_param_quote(val, options = {})
|
218
|
-
options[:quote] ||= '"'
|
219
|
-
unless val =~ /^[a-zA-Z0-9$_\-\^]+$/
|
220
|
-
val = options[:quote] +
|
221
|
-
# Yes, we need crazy escaping here, to deal with regexp esc too!
|
222
|
-
val.gsub("'", "\\\\\'").gsub('"', "\\\\\"") +
|
223
|
-
options[:quote]
|
224
|
-
end
|
225
|
-
return val
|
226
|
-
end
|
227
|
-
|
228
|
-
private
|
229
|
-
|
230
|
-
##
|
231
|
-
# Convert a facet/value pair into a solr fq parameter
|
232
|
-
def facet_value_to_fq_string(facet_field, value)
|
233
|
-
facet_config = blacklight_config.facet_fields[facet_field]
|
234
|
-
|
235
|
-
solr_field = facet_config.field if facet_config and not facet_config.query
|
236
|
-
solr_field ||= facet_field
|
237
|
-
|
238
|
-
local_params = []
|
239
|
-
local_params << "tag=#{facet_config.tag}" if facet_config and facet_config.tag
|
240
|
-
|
241
|
-
prefix = ""
|
242
|
-
prefix = "{!#{local_params.join(" ")}}" unless local_params.empty?
|
243
|
-
|
244
|
-
fq = case
|
245
|
-
when (facet_config and facet_config.query)
|
246
|
-
facet_config.query[value][:fq]
|
247
|
-
when (facet_config and facet_config.date)
|
248
|
-
# in solr 3.2+, this could be replaced by a !term query
|
249
|
-
"#{prefix}#{solr_field}:#{RSolr.solr_escape(value)}"
|
250
|
-
when (value.is_a?(DateTime) or value.is_a?(Date) or value.is_a?(Time))
|
251
|
-
"#{prefix}#{solr_field}:#{RSolr.solr_escape(value.to_time.utc.strftime("%Y-%m-%dT%H:%M:%SZ"))}"
|
252
|
-
when (value.is_a?(TrueClass) or value.is_a?(FalseClass) or value == 'true' or value == 'false'),
|
253
|
-
(value.is_a?(Integer) or (value.to_i.to_s == value if value.respond_to? :to_i)),
|
254
|
-
(value.is_a?(Float) or (value.to_f.to_s == value if value.respond_to? :to_f))
|
255
|
-
"#{prefix}#{solr_field}:#{RSolr.solr_escape(value.to_s)}"
|
256
|
-
when value.is_a?(Range)
|
257
|
-
"#{prefix}#{solr_field}:[#{value.first} TO #{value.last}]"
|
258
|
-
else
|
259
|
-
"{!raw f=#{solr_field}#{(" " + local_params.join(" ")) unless local_params.empty?}}#{value}"
|
260
|
-
end
|
261
|
-
end
|
262
|
-
|
263
|
-
##
|
264
|
-
# The key to use to retrieve the grouped field to display
|
265
|
-
def grouped_key_for_results
|
266
|
-
blacklight_config.index.group
|
267
|
-
end
|
4
|
+
include Blacklight::Solr::SearchBuilderBehavior
|
268
5
|
end
|
269
6
|
end
|
@@ -0,0 +1,274 @@
|
|
1
|
+
module Blacklight::Solr
|
2
|
+
module SearchBuilderBehavior
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
self.default_processor_chain = [:default_solr_parameters, :add_query_to_solr, :add_facet_fq_to_solr, :add_facetting_to_solr, :add_solr_fields_to_query, :add_paging_to_solr, :add_sorting_to_solr, :add_group_config_to_solr ]
|
7
|
+
end
|
8
|
+
|
9
|
+
####
|
10
|
+
# Start with general defaults from BL config. Need to use custom
|
11
|
+
# merge to dup values, to avoid later mutating the original by mistake.
|
12
|
+
def default_solr_parameters(solr_parameters)
|
13
|
+
blacklight_config.default_solr_params.each do |key, value|
|
14
|
+
solr_parameters[key] = if value.respond_to? :deep_dup
|
15
|
+
value.deep_dup
|
16
|
+
elsif value.respond_to? :dup and value.duplicable?
|
17
|
+
value.dup
|
18
|
+
else
|
19
|
+
value
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
##
|
25
|
+
# Take the user-entered query, and put it in the solr params,
|
26
|
+
# including config's "search field" params for current search field.
|
27
|
+
# also include setting spellcheck.q.
|
28
|
+
def add_query_to_solr(solr_parameters)
|
29
|
+
###
|
30
|
+
# Merge in search field configured values, if present, over-writing general
|
31
|
+
# defaults
|
32
|
+
###
|
33
|
+
# legacy behavior of user param :qt is passed through, but over-ridden
|
34
|
+
# by actual search field config if present. We might want to remove
|
35
|
+
# this legacy behavior at some point. It does not seem to be currently
|
36
|
+
# rspec'd.
|
37
|
+
solr_parameters[:qt] = blacklight_params[:qt] if blacklight_params[:qt]
|
38
|
+
|
39
|
+
if search_field
|
40
|
+
solr_parameters[:qt] = search_field.qt
|
41
|
+
solr_parameters.merge!( search_field.solr_parameters) if search_field.solr_parameters
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Create Solr 'q' including the user-entered q, prefixed by any
|
46
|
+
# solr LocalParams in config, using solr LocalParams syntax.
|
47
|
+
# http://wiki.apache.org/solr/LocalParams
|
48
|
+
##
|
49
|
+
if (search_field && hash = search_field.solr_local_parameters)
|
50
|
+
local_params = hash.collect do |key, val|
|
51
|
+
key.to_s + "=" + solr_param_quote(val, :quote => "'")
|
52
|
+
end.join(" ")
|
53
|
+
solr_parameters[:q] = "{!#{local_params}}#{blacklight_params[:q]}"
|
54
|
+
|
55
|
+
##
|
56
|
+
# Set Solr spellcheck.q to be original user-entered query, without
|
57
|
+
# our local params, otherwise it'll try and spellcheck the local
|
58
|
+
# params!
|
59
|
+
solr_parameters["spellcheck.q"] ||= blacklight_params[:q]
|
60
|
+
elsif blacklight_params[:q].is_a? Hash
|
61
|
+
q = blacklight_params[:q]
|
62
|
+
solr_parameters[:q] = if q.values.any?(&:blank?)
|
63
|
+
# if any field parameters are empty, exclude _all_ results
|
64
|
+
"{!lucene}NOT *:*"
|
65
|
+
else
|
66
|
+
"{!lucene}" + q.map do |field, values|
|
67
|
+
"#{field}:(#{ Array(values).map { |x| solr_param_quote(x) }.join(" OR ")})"
|
68
|
+
end.join(" AND ")
|
69
|
+
end
|
70
|
+
|
71
|
+
solr_parameters[:spellcheck] = 'false'
|
72
|
+
elsif blacklight_params[:q]
|
73
|
+
solr_parameters[:q] = blacklight_params[:q]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Add any existing facet limits, stored in app-level HTTP query
|
79
|
+
# as :f, to solr as appropriate :fq query.
|
80
|
+
def add_facet_fq_to_solr(solr_parameters)
|
81
|
+
|
82
|
+
# convert a String value into an Array
|
83
|
+
if solr_parameters[:fq].is_a? String
|
84
|
+
solr_parameters[:fq] = [solr_parameters[:fq]]
|
85
|
+
end
|
86
|
+
|
87
|
+
# :fq, map from :f.
|
88
|
+
if ( blacklight_params[:f])
|
89
|
+
f_request_params = blacklight_params[:f]
|
90
|
+
|
91
|
+
f_request_params.each_pair do |facet_field, value_list|
|
92
|
+
Array(value_list).each do |value|
|
93
|
+
next if value.blank? # skip empty strings
|
94
|
+
solr_parameters.append_filter_query facet_value_to_fq_string(facet_field, value)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Add appropriate Solr facetting directives in, including
|
102
|
+
# taking account of our facet paging/'more'. This is not
|
103
|
+
# about solr 'fq', this is about solr facet.* params.
|
104
|
+
def add_facetting_to_solr(solr_parameters)
|
105
|
+
# While not used by BL core behavior, legacy behavior seemed to be
|
106
|
+
# to accept incoming params as "facet.field" or "facets", and add them
|
107
|
+
# on to any existing facet.field sent to Solr. Legacy behavior seemed
|
108
|
+
# to be accepting these incoming params as arrays (in Rails URL with []
|
109
|
+
# on end), or single values. At least one of these is used by
|
110
|
+
# Stanford for "faux hieararchial facets".
|
111
|
+
if blacklight_params.has_key?("facet.field") || blacklight_params.has_key?("facets")
|
112
|
+
solr_parameters[:"facet.field"].concat( [blacklight_params["facet.field"], blacklight_params["facets"]].flatten.compact ).uniq!
|
113
|
+
end
|
114
|
+
|
115
|
+
blacklight_config.facet_fields.select { |field_name,facet|
|
116
|
+
facet.include_in_request || (facet.include_in_request.nil? && blacklight_config.add_facet_fields_to_solr_request)
|
117
|
+
}.each do |field_name, facet|
|
118
|
+
solr_parameters[:facet] ||= true
|
119
|
+
|
120
|
+
case
|
121
|
+
when facet.pivot
|
122
|
+
solr_parameters.append_facet_pivot with_ex_local_param(facet.ex, facet.pivot.join(","))
|
123
|
+
when facet.query
|
124
|
+
solr_parameters.append_facet_query facet.query.map { |k, x| with_ex_local_param(facet.ex, x[:fq]) }
|
125
|
+
else
|
126
|
+
solr_parameters.append_facet_fields with_ex_local_param(facet.ex, facet.field)
|
127
|
+
end
|
128
|
+
|
129
|
+
if facet.sort
|
130
|
+
solr_parameters[:"f.#{facet.field}.facet.sort"] = facet.sort
|
131
|
+
end
|
132
|
+
|
133
|
+
if facet.solr_params
|
134
|
+
facet.solr_params.each do |k, v|
|
135
|
+
solr_parameters[:"f.#{facet.field}.#{k}"] = v
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Support facet paging and 'more'
|
140
|
+
# links, by sending a facet.limit one more than what we
|
141
|
+
# want to page at, according to configured facet limits.
|
142
|
+
solr_parameters[:"f.#{facet.field}.facet.limit"] = (facet_limit_for(field_name) + 1) if facet_limit_for(field_name)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def add_solr_fields_to_query solr_parameters
|
147
|
+
blacklight_config.show_fields.select(&method(:should_add_field_to_request?)).each do |field_name, field|
|
148
|
+
if field.solr_params
|
149
|
+
field.solr_params.each do |k, v|
|
150
|
+
solr_parameters[:"f.#{field.field}.#{k}"] = v
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
blacklight_config.index_fields.select(&method(:should_add_field_to_request?)).each do |field_name, field|
|
156
|
+
if field.highlight
|
157
|
+
solr_parameters[:hl] = true
|
158
|
+
solr_parameters.append_highlight_field field.field
|
159
|
+
end
|
160
|
+
|
161
|
+
if field.solr_params
|
162
|
+
field.solr_params.each do |k, v|
|
163
|
+
solr_parameters[:"f.#{field.field}.#{k}"] = v
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
###
|
170
|
+
# copy paging params from BL app over to solr, changing
|
171
|
+
# app level per_page and page to Solr rows and start.
|
172
|
+
def add_paging_to_solr(solr_params)
|
173
|
+
rows(solr_params[:rows] || 10) if rows.nil?
|
174
|
+
|
175
|
+
solr_params[:rows] = rows
|
176
|
+
|
177
|
+
if start != 0
|
178
|
+
solr_params[:start] = start
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
###
|
183
|
+
# copy sorting params from BL app over to solr
|
184
|
+
def add_sorting_to_solr(solr_parameters)
|
185
|
+
solr_parameters[:sort] = sort unless sort.blank?
|
186
|
+
end
|
187
|
+
|
188
|
+
# Remove the group parameter if we've faceted on the group field (e.g. for the full results for a group)
|
189
|
+
def add_group_config_to_solr solr_parameters
|
190
|
+
if blacklight_params[:f] and blacklight_params[:f][grouped_key_for_results]
|
191
|
+
solr_parameters[:group] = false
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def with_ex_local_param(ex, value)
|
196
|
+
if ex
|
197
|
+
"{!ex=#{ex}}#{value}"
|
198
|
+
else
|
199
|
+
value
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
# Look up facet limit for given facet_field. Will look at config, and
|
204
|
+
# if config is 'true' will look up from Solr @response if available. If
|
205
|
+
# no limit is avaialble, returns nil. Used from #add_facetting_to_solr
|
206
|
+
# to supply f.fieldname.facet.limit values in solr request (no @response
|
207
|
+
# available), and used in display (with @response available) to create
|
208
|
+
# a facet paginator with the right limit.
|
209
|
+
def facet_limit_for(facet_field)
|
210
|
+
facet = blacklight_config.facet_fields[facet_field]
|
211
|
+
return if facet.blank?
|
212
|
+
|
213
|
+
if facet.limit
|
214
|
+
facet.limit == true ? blacklight_config.default_facet_limit : facet.limit
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
##
|
219
|
+
# A helper method used for generating solr LocalParams, put quotes
|
220
|
+
# around the term unless it's a bare-word. Escape internal quotes
|
221
|
+
# if needed.
|
222
|
+
def solr_param_quote(val, options = {})
|
223
|
+
options[:quote] ||= '"'
|
224
|
+
unless val =~ /^[a-zA-Z0-9$_\-\^]+$/
|
225
|
+
val = options[:quote] +
|
226
|
+
# Yes, we need crazy escaping here, to deal with regexp esc too!
|
227
|
+
val.gsub("'", "\\\\\'").gsub('"', "\\\\\"") +
|
228
|
+
options[:quote]
|
229
|
+
end
|
230
|
+
return val
|
231
|
+
end
|
232
|
+
|
233
|
+
private
|
234
|
+
|
235
|
+
##
|
236
|
+
# Convert a facet/value pair into a solr fq parameter
|
237
|
+
def facet_value_to_fq_string(facet_field, value)
|
238
|
+
facet_config = blacklight_config.facet_fields[facet_field]
|
239
|
+
|
240
|
+
solr_field = facet_config.field if facet_config and not facet_config.query
|
241
|
+
solr_field ||= facet_field
|
242
|
+
|
243
|
+
local_params = []
|
244
|
+
local_params << "tag=#{facet_config.tag}" if facet_config and facet_config.tag
|
245
|
+
|
246
|
+
prefix = ""
|
247
|
+
prefix = "{!#{local_params.join(" ")}}" unless local_params.empty?
|
248
|
+
|
249
|
+
fq = case
|
250
|
+
when (facet_config and facet_config.query)
|
251
|
+
facet_config.query[value][:fq]
|
252
|
+
when (facet_config and facet_config.date)
|
253
|
+
# in solr 3.2+, this could be replaced by a !term query
|
254
|
+
"#{prefix}#{solr_field}:#{RSolr.solr_escape(value)}"
|
255
|
+
when (value.is_a?(DateTime) or value.is_a?(Date) or value.is_a?(Time))
|
256
|
+
"#{prefix}#{solr_field}:#{RSolr.solr_escape(value.to_time.utc.strftime("%Y-%m-%dT%H:%M:%SZ"))}"
|
257
|
+
when (value.is_a?(TrueClass) or value.is_a?(FalseClass) or value == 'true' or value == 'false'),
|
258
|
+
(value.is_a?(Integer) or (value.to_i.to_s == value if value.respond_to? :to_i)),
|
259
|
+
(value.is_a?(Float) or (value.to_f.to_s == value if value.respond_to? :to_f))
|
260
|
+
"#{prefix}#{solr_field}:#{RSolr.solr_escape(value.to_s)}"
|
261
|
+
when value.is_a?(Range)
|
262
|
+
"#{prefix}#{solr_field}:[#{value.first} TO #{value.last}]"
|
263
|
+
else
|
264
|
+
"{!raw f=#{solr_field}#{(" " + local_params.join(" ")) unless local_params.empty?}}#{value}"
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
##
|
269
|
+
# The key to use to retrieve the grouped field to display
|
270
|
+
def grouped_key_for_results
|
271
|
+
blacklight_config.index.group
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|