multi-solr 01.01.05
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.
- data/.gitignore +6 -0
- data/.rspec +1 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/lib/multi_solr/base_searcher.rb +393 -0
- data/lib/multi_solr/filter_value_composite.rb +33 -0
- data/lib/multi_solr/rails_form_render_helper.rb +84 -0
- data/lib/multi_solr/search_request.rb +209 -0
- data/lib/multi_solr/search_result.rb +127 -0
- data/lib/multi_solr/single_core_handler.rb +341 -0
- data/lib/multi_solr/solr_filter_collection.rb +97 -0
- data/lib/multi_solr/solr_filter_date.rb +46 -0
- data/lib/multi_solr/solr_filter_date_range.rb +62 -0
- data/lib/multi_solr/solr_filter_free_query.rb +11 -0
- data/lib/multi_solr/solr_filter_simple.rb +96 -0
- data/lib/multi_solr/timeline_core_handler.rb +131 -0
- data/lib/multi_solr/version.rb +3 -0
- data/lib/multi_solr.rb +43 -0
- data/multi-solr.gemspec +28 -0
- data/spec/fixtures/solr-testdata.yml +13 -0
- data/spec/multi_solr/base_searcher_spec.rb +212 -0
- data/spec/multi_solr/search_request_spec.rb +45 -0
- data/spec/multi_solr/search_result_spec.rb +113 -0
- data/spec/multi_solr/single_core_handler_spec.rb +169 -0
- data/spec/multi_solr/timeline_core_handler_spec.rb +107 -0
- data/spec/solr_test_helper.rb +15 -0
- data/spec/solr_testdata_provider.rb +89 -0
- data/spec/spec_helper.rb +27 -0
- data/test-solr/.gitignore +4 -0
- data/test-solr/articles.xml +6 -0
- data/test-solr/etc/jetty.xml +227 -0
- data/test-solr/etc/webdefault.xml +410 -0
- data/test-solr/lib/jetty-6.1.26-patched-JETTY-1340.jar +0 -0
- data/test-solr/lib/jetty-LICENSE.txt +202 -0
- data/test-solr/lib/jetty-NOTICE.txt +36 -0
- data/test-solr/lib/jetty-util-6.1.26-patched-JETTY-1340.jar +0 -0
- data/test-solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
- data/test-solr/lib/jsp-2.1/jsp-2.1-glassfish-2.1.v20091210.jar +0 -0
- data/test-solr/lib/jsp-2.1/jsp-2.1-jetty-6.1.26.jar +0 -0
- data/test-solr/lib/jsp-2.1/jsp-api-2.1-glassfish-2.1.v20091210.jar +0 -0
- data/test-solr/lib/lukeall-3.4.0_1.jar +0 -0
- data/test-solr/lib/servlet-api-2.5-20081211.jar +0 -0
- data/test-solr/solr/lib/apache-solr-dataimporthandler-3.4.0.jar +0 -0
- data/test-solr/solr/solr.xml +20 -0
- data/test-solr/solr/testcore/conf/dataimport-test.xml +12 -0
- data/test-solr/solr/testcore/conf/schema.xml +42 -0
- data/test-solr/solr/testcore/conf/solr_schema.css +58 -0
- data/test-solr/solr/testcore/conf/solr_schema.xsl +72 -0
- data/test-solr/solr/testcore/conf/solrconfig.xml +72 -0
- data/test-solr/start-test-solr.sh +10 -0
- data/test-solr/start.jar +0 -0
- data/test-solr/webapps/solr.war +0 -0
- metadata +212 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,393 @@
|
|
1
|
+
# Basis-Suchmodule für SOLR-Indizies
|
2
|
+
|
3
|
+
require 'rsolr'
|
4
|
+
require "active_support/core_ext/class/attribute_accessors"
|
5
|
+
|
6
|
+
module MultiSolr::BaseSearcher
|
7
|
+
|
8
|
+
|
9
|
+
# Erweitern einer Searcher-Class um Basis-Solr-Funktionen
|
10
|
+
#
|
11
|
+
def self.included(base)
|
12
|
+
base.class_eval do
|
13
|
+
|
14
|
+
cattr_accessor :solr_url # String mit der Base-Solr-Url (ohne Core-Anteil!)
|
15
|
+
|
16
|
+
cattr_accessor :result_class do # die zu nutzende Klasse für das Suchergebnis
|
17
|
+
MultiSolr::SearchResult
|
18
|
+
end
|
19
|
+
|
20
|
+
cattr_accessor :facet_enum_fields do # Array mit den Namen der Felder, die die Facet-Enum-Methode für Facets nutzen (Felder mit kleinen Wertebereichen)
|
21
|
+
[]
|
22
|
+
end
|
23
|
+
|
24
|
+
# der zu verwendende SOLR-Core, wird per default aus dem Klassennamen gebildet
|
25
|
+
# Beispiel: ContainerSearcher => 'core-container'
|
26
|
+
cattr_accessor(:core_name, :instance_reader => false, :instance_writer => false) do
|
27
|
+
m = self.name.match(/(\w+::)*(\w+)Searcher/)
|
28
|
+
if m
|
29
|
+
c = m[2].downcase
|
30
|
+
name = "core-#{c}"
|
31
|
+
else
|
32
|
+
name = 'core-default'
|
33
|
+
end
|
34
|
+
name
|
35
|
+
end
|
36
|
+
|
37
|
+
attr_accessor :fieldlist # Field-List (siehe Solr-Doku fl-Parameter), default ist *
|
38
|
+
attr_accessor :facets_only # wenn true, dann nur Facets ermittlen
|
39
|
+
attr_accessor :without_facets # wenn true, dann auf Facets verzichten
|
40
|
+
attr_accessor :result_format # Rückgabe-Format (json, xml), wenn nicht gesetzt wird "ruby" geliefert; Ist es gesetzt wird das Ergebnis nicht geparst (also raw als String zurückgegeben)
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
base.extend ClassMethods
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
module ClassMethods
|
49
|
+
|
50
|
+
def set_solr_url url
|
51
|
+
self.solr_url = url
|
52
|
+
end
|
53
|
+
|
54
|
+
# Setzen des CORE-Namens
|
55
|
+
def set_core_name name
|
56
|
+
self.core_name = name
|
57
|
+
end
|
58
|
+
|
59
|
+
def set_result_class clasz
|
60
|
+
self.result_class = clasz
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
# Setzen der Feldnamen, die bei Facetierung die Facet-Enum-Methode des SOLR nutzen sollen
|
65
|
+
def set_facet_enum_fields *field_names
|
66
|
+
self.facet_enum_fields += field_names
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
# Ermittelt und cached die möglichen Werte der als pre_cache_value_fields definierten Felder
|
71
|
+
# Diese werden im Rails-Cache zwischengespeichert
|
72
|
+
# Ansonsten see BaseSearcher.list_possible_values
|
73
|
+
# zusätzlicher Parameter:
|
74
|
+
# expires_in: optional, Gültigkeit des Cache-Wertes in Sekunden, default ist 1 Stunde
|
75
|
+
#
|
76
|
+
def cached_list_possible_values fieldname, context=nil, searcher_options=nil, expires_in=1.hours
|
77
|
+
cache_key = "solr-#{self.core_name}-#{context}-#{fieldname}-values"
|
78
|
+
values = MultiSolr.cache.read(cache_key)
|
79
|
+
if values.nil?
|
80
|
+
# dann sind noch gar keine Werte gecached => diese holen
|
81
|
+
values = list_possible_values fieldname, context, searcher_options
|
82
|
+
# und nun im Cache ablegen
|
83
|
+
MultiSolr.logger.debug "#{name}.cached_list_possible_values: write in cache '#{cache_key}' => #{values.inspect}" if MultiSolr.logger.debug?
|
84
|
+
MultiSolr.cache.write(cache_key, values, :expires_in => expires_in)
|
85
|
+
end
|
86
|
+
values
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
# Liefert zu dem spezifizierten Kontext und Feld die möglichen Werte
|
91
|
+
# Parameter:
|
92
|
+
# fieldname: Name des Feldes (als Symbol)
|
93
|
+
# context: optionales Object mit weiteren Context-Informationen, dieser wird an den Force-Query-Builder übergeben
|
94
|
+
# searcher_options: optinale Hash mit Optionen für den hier intern erzeugten Searcher (see self.initialize)
|
95
|
+
# Beispiel:
|
96
|
+
# searcher.list_possible_values :lkz, :whs_id => 5
|
97
|
+
#
|
98
|
+
def list_possible_values fieldname, context=nil, searcher_options=nil
|
99
|
+
s_request = MultiSolr::SearchRequest.new :facets => [fieldname]
|
100
|
+
searcher_options ||= {}
|
101
|
+
searcher = self.new(searcher_options.merge(:facets_only => true))
|
102
|
+
result = searcher.execute(s_request, context)
|
103
|
+
facet_counts = result.facet_counts
|
104
|
+
values = []
|
105
|
+
if MultiSolr.logger.debug?
|
106
|
+
MultiSolr.logger.debug "#{name}.list_possible_values(#{fieldname}, #{context.inspect}): facet_counts=#{facet_counts.inspect}"
|
107
|
+
end
|
108
|
+
if facet_counts
|
109
|
+
value_pairs = facet_counts[fieldname.to_s]
|
110
|
+
if value_pairs && !value_pairs.empty?
|
111
|
+
# das value_pairs besteht Paar-weise aus Value und Anzahl
|
112
|
+
# Es werden hier nur die Values gebraucht, wo die Anzahl >0 ist
|
113
|
+
value_pairs.each do |value_count_pair|
|
114
|
+
val, count = value_count_pair
|
115
|
+
if val && count > 0
|
116
|
+
# wenn val nur aus Zahlen besteht, dann nach Integer konvertieren (wegen der Sortierung)
|
117
|
+
val = val.to_i if val =~ /\d+/
|
118
|
+
values << val
|
119
|
+
end
|
120
|
+
end
|
121
|
+
values.sort!
|
122
|
+
end
|
123
|
+
end
|
124
|
+
if MultiSolr.logger.debug?
|
125
|
+
MultiSolr.logger.debug "#{name}.list_possible_values(#{fieldname}, #{context.inspect}) => #{values.inspect}"
|
126
|
+
end
|
127
|
+
values
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
# Liefert RSolr-Connection (RSolr.connect) zum konfigurierten SOLR-Server(see solr_url)
|
132
|
+
# und konfiguriertem Core (see core_name)
|
133
|
+
def solr_connection
|
134
|
+
url = self.solr_url || raise("no solr-url configured!")
|
135
|
+
url = "#{url}/#{self.core_name}" if self.core_name
|
136
|
+
MultiSolr.logger.debug("solr_connection: url==#{url}")
|
137
|
+
RSolr.connect :url => url
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
# sendet Ping an SOLR-Instance
|
142
|
+
# returns true if ok
|
143
|
+
def ping
|
144
|
+
self.solr_connection.head("admin/ping").response[:status] == 200
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
# ermitteln Zeitstempel des letzten Datenimports
|
149
|
+
def import_status solr_core_import_handler_propfile_path
|
150
|
+
MultiSolr.cache.fetch("Solr.import_status.#{self.core_name}.#{solr_core_import_handler_propfile_path}", :expires_in => 900) do
|
151
|
+
result = 'unbekannt'
|
152
|
+
begin
|
153
|
+
raise("Solr-Import-Status-Propertiesfile not exist") unless File.exist?(solr_core_import_handler_propfile_path)
|
154
|
+
matcher = /^last_index_time=(.*)$/
|
155
|
+
data = File.read(solr_core_import_handler_propfile_path)
|
156
|
+
match = matcher.match(data)
|
157
|
+
if match
|
158
|
+
result = match[1]
|
159
|
+
result.gsub!('\\', '') # Zeit enthält \ vor :
|
160
|
+
result = result[0...-3] # Sekunden entfernen
|
161
|
+
end
|
162
|
+
rescue => ex
|
163
|
+
MultiSolr.logger.warn "SolrSearch.import_status: source=#{solr_core_import_handler_propfile_path}, error=#{ex.message}\n\t"+ex.backtrace.join("\n\t")
|
164
|
+
end
|
165
|
+
MultiSolr.logger.info "SolrSearch.import_status: #{solr_core_import_handler_propfile_path}, result=#{result}"
|
166
|
+
result
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
# liefert einzelnes Solr-Dokument an Hand der Id
|
172
|
+
# Parameter:
|
173
|
+
# id: die gewünschte Id (Integer oder String)
|
174
|
+
# id_field_name : optional, der Name des ID-Fields, default ist 'id'
|
175
|
+
def get_doc_by_id(id, id_field_name=:id)
|
176
|
+
solr_result = solr_connection.get 'select', :params => {:q => "#{id_field_name}:#{id}", :rows => 1}
|
177
|
+
docs = solr_result['response']['docs']
|
178
|
+
return nil if docs.nil? || docs.empty?
|
179
|
+
docs.first
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|
183
|
+
# ===== ENDE der Class-Methods =====
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
# ===== START Instance-Methods =====
|
188
|
+
|
189
|
+
|
190
|
+
# Constructor
|
191
|
+
# params:
|
192
|
+
# options: optionaler Hash mit Options (als Option sind aller hier definierten Attribute erlaubt)
|
193
|
+
def initialize options=nil
|
194
|
+
if options
|
195
|
+
options.each do |k,v|
|
196
|
+
self.send("#{k}=", v)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# liefert lokalen Core-Namen und wenn nicht gesetzt den globalen Core-Namen (in der Klasse definierten)
|
202
|
+
def core_name
|
203
|
+
@core_name || self.class.core_name
|
204
|
+
end
|
205
|
+
|
206
|
+
|
207
|
+
# setzt lokalen Core-Namen ohne den globalen Core-Namen (in der Klasse definiert) zu ändern
|
208
|
+
def core_name=(name)
|
209
|
+
@core_name = name
|
210
|
+
end
|
211
|
+
|
212
|
+
|
213
|
+
# liefert SOLR-Connection
|
214
|
+
def solr_connection
|
215
|
+
return @solr_connection if @solr_connection
|
216
|
+
url = self.class.solr_url || raise("no solr-url configured!")
|
217
|
+
url = "#{url}/#{self.core_name}" if self.core_name
|
218
|
+
MultiSolr.logger.debug("solr_connection: url==#{url}")
|
219
|
+
@solr_connection = RSolr.connect :url => url
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
|
224
|
+
# Ausführen der Suche / Recherche
|
225
|
+
# params:
|
226
|
+
# solr_search_request: die Suchanfrage als SolrSearchRequest-Instance
|
227
|
+
# context: Hash mit weiteren Context-Informationen, dieser wird u.a. an den Force-Query-Builder übergeben
|
228
|
+
def execute solr_search_request, context=nil
|
229
|
+
solr_params = build_solr_params solr_search_request, context
|
230
|
+
solr_result = solr_connection.get 'select', :params => solr_params
|
231
|
+
|
232
|
+
# RAW-Result liefern wenn Result-Format gesetzt ist
|
233
|
+
return solr_result if self.result_format
|
234
|
+
|
235
|
+
# Parsen des Ergebnisses
|
236
|
+
result = self.result_class.new solr_result, solr_search_request, context
|
237
|
+
result
|
238
|
+
end
|
239
|
+
|
240
|
+
|
241
|
+
# Bilden der SOLR-Parameter für eine SOLR-Anfrage
|
242
|
+
# params:
|
243
|
+
# solr_search_request: die Suchanfrage als SolrSearchRequest-Instance
|
244
|
+
# context: Hash mit weiteren Context-Informationen, dieser wird an den Force-Query-Builder übergeben
|
245
|
+
# returns: Hash mit den SOLR-Parametern
|
246
|
+
def build_solr_params solr_search_request, context=nil
|
247
|
+
solr_params = {}
|
248
|
+
solr_params['stats.field'] = []
|
249
|
+
|
250
|
+
fq_params = self.force_query_params context
|
251
|
+
if fq_params && fq_params.is_a?(Hash)
|
252
|
+
fq = []
|
253
|
+
fq_params.each{|k, v| fq << "#{k}:#{v}"}
|
254
|
+
solr_params[:fq] = fq.join(' ')
|
255
|
+
end
|
256
|
+
|
257
|
+
q = solr_search_request.build_query
|
258
|
+
q = "*:*" if q.blank? # wenn keine Query angegeben ist, dann nach allem Suchen
|
259
|
+
solr_params[:q] = q
|
260
|
+
|
261
|
+
# Fieldlist
|
262
|
+
if q['_val_:']
|
263
|
+
# dann enthält die Query eine query-function
|
264
|
+
# Der Wert dieser wird immer im field "score" abgelegt
|
265
|
+
# daher dieses Feld zur Feldliste hinzufügen
|
266
|
+
if self.fieldlist
|
267
|
+
self.fieldlist << ',score' unless self.fieldlist[',score']
|
268
|
+
else
|
269
|
+
self.fieldlist = '*,score'
|
270
|
+
end
|
271
|
+
end
|
272
|
+
solr_params[:fl] = self.fieldlist if self.fieldlist
|
273
|
+
|
274
|
+
# Sortierung
|
275
|
+
if solr_search_request.sorts && !solr_search_request.sorts.empty?
|
276
|
+
solr_search_request.sorts.delete_if{|s| s.blank?}
|
277
|
+
solr_params[:sort] = solr_search_request.sorts.map{|s| s =~ /\s(asc|desc)$/ ? s : "#{s} asc"}.join(',')
|
278
|
+
end
|
279
|
+
|
280
|
+
# Facets
|
281
|
+
if !self.without_facets && solr_search_request.facets
|
282
|
+
parse_facets solr_search_request, solr_params
|
283
|
+
end
|
284
|
+
|
285
|
+
# Stats
|
286
|
+
if solr_search_request.stats_fields && !solr_search_request.stats_fields.empty?
|
287
|
+
s_fields = solr_search_request.stats_fields.select{|f| !f.blank?}
|
288
|
+
unless s_fields.empty?
|
289
|
+
solr_params[:stats] = true
|
290
|
+
solr_params['stats.field'] += s_fields
|
291
|
+
end
|
292
|
+
end
|
293
|
+
solr_params['stats.field'].map!{|f| f.to_s}.uniq!
|
294
|
+
|
295
|
+
# Gruppierung
|
296
|
+
if !solr_search_request.group_field.blank? && !self.facets_only
|
297
|
+
solr_params[:group] = true
|
298
|
+
solr_params['group.field'] = solr_search_request.group_field
|
299
|
+
solr_params['group.ngroups'] = true
|
300
|
+
solr_params['group.limit'] = solr_search_request.group_size || 1
|
301
|
+
solr_params['group.truncate'] = true if solr_params[:facet] && solr_search_request.group_truncate
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
# Paginierung
|
306
|
+
if self.facets_only
|
307
|
+
solr_params[:rows] = 0
|
308
|
+
else
|
309
|
+
solr_params[:rows] = solr_search_request.page_size
|
310
|
+
solr_params[:start] = (solr_search_request.page-1) * solr_search_request.page_size
|
311
|
+
end
|
312
|
+
|
313
|
+
# Ausgabe-Format
|
314
|
+
solr_params[:wt] = self.result_format if self.result_format
|
315
|
+
|
316
|
+
if MultiSolr.logger.debug?
|
317
|
+
MultiSolr.logger.debug "SolrSearch#build_solr_params: #{self.inspect}\n\tSEARCH-REQUEST=#{solr_search_request.inspect}\n\t=> SOLR_PARAMS=#{solr_params.inspect}\n"
|
318
|
+
end
|
319
|
+
solr_params
|
320
|
+
end
|
321
|
+
|
322
|
+
|
323
|
+
protected
|
324
|
+
|
325
|
+
# liefert wenn notwendig die Parameter als Hash für eine SOLR-Force-Query
|
326
|
+
# sollte bei Bedarf von der nutzenden Klasse überschrieben werden.
|
327
|
+
# params:
|
328
|
+
# context: Hash mit weiteren Context-Informationen
|
329
|
+
def force_query_params context
|
330
|
+
context
|
331
|
+
end
|
332
|
+
|
333
|
+
|
334
|
+
private
|
335
|
+
|
336
|
+
|
337
|
+
# Bilden der Facet-Solr-Params aus den Facet-Definitionen des Requests
|
338
|
+
def parse_facets solr_search_request, solr_params
|
339
|
+
solr_search_request.facets.delete_if(&:blank?) # leer Elemente entfernen
|
340
|
+
return if solr_search_request.facets.empty?
|
341
|
+
|
342
|
+
solr_params['facet.field'] = []
|
343
|
+
solr_params['facet.range'] = []
|
344
|
+
facet_params = solr_search_request.facet_params || {}
|
345
|
+
solr_search_request.facets.map(&:to_sym).each do |facet_field|
|
346
|
+
field_facet_params = facet_params[facet_field] || {}
|
347
|
+
stats_facet_field = field_facet_params[:stats_field]
|
348
|
+
if stats_facet_field
|
349
|
+
# dann Facet per Stats-Componente
|
350
|
+
solr_params[:stats] = true
|
351
|
+
if stats_facet_field.is_a?(Array)
|
352
|
+
solr_params['stats.field'] += stats_facet_field
|
353
|
+
else
|
354
|
+
solr_params['stats.field'] << stats_facet_field
|
355
|
+
stats_facet_field = [stats_facet_field]
|
356
|
+
end
|
357
|
+
stats_facet_field.each do |sfield_name|
|
358
|
+
solr_params["f.#{sfield_name}.stats.facet"] ||= []
|
359
|
+
solr_params["f.#{sfield_name}.stats.facet"] << facet_field
|
360
|
+
end
|
361
|
+
else
|
362
|
+
solr_params[:facet] = true
|
363
|
+
if field_facet_params[:range]
|
364
|
+
# Range-Facet
|
365
|
+
solr_params[:facet] = true
|
366
|
+
solr_params['facet.range'] << facet_field
|
367
|
+
field_facet_params[:end] ||= 'NOW/DAY'
|
368
|
+
field_facet_params[:gap] ||= '+1DAY'
|
369
|
+
field_facet_params.each do |option_name, value|
|
370
|
+
solr_params["f.#{facet_field}.facet.range.#{option_name}"] = value
|
371
|
+
end
|
372
|
+
else
|
373
|
+
# normale Facet-Field
|
374
|
+
solr_params['facet.field'] << facet_field
|
375
|
+
field_facet_params[:mincount] ||= 1 # Facets ohne Treffer ignorieren
|
376
|
+
# Nutzen der Facet-Enum-Methode fuer spezielle Felder (Felder mit kleinen Wertebereichen)
|
377
|
+
field_facet_params['method'] = 'enum' if self.facet_enum_fields.include?(facet_field)
|
378
|
+
|
379
|
+
field_facet_params.each do |option_name, value|
|
380
|
+
solr_params["f.#{facet_field}.facet.#{option_name}"] = value
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
384
|
+
end
|
385
|
+
if solr_params[:facet]
|
386
|
+
# Umschalten der Facet-Ergebnisse in Array-Darstellung
|
387
|
+
# (der json.nl-Schalter wirkt auch bei Ruby siehe http://wiki.apache.org/solr/SolJSON)
|
388
|
+
solr_params['json.nl'] = 'arrarr'
|
389
|
+
end
|
390
|
+
|
391
|
+
end
|
392
|
+
|
393
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Composite-Klasse von Filter und Filter-Value
|
2
|
+
|
3
|
+
class MultiSolr::FilterValueComposite
|
4
|
+
|
5
|
+
attr_accessor :filter
|
6
|
+
attr_accessor :value
|
7
|
+
|
8
|
+
# Constructor
|
9
|
+
# Params:
|
10
|
+
# filter: konkrete Filter-Instance (i.a. ein MultiSolr::SolrFilterSimple oder eine Subklasse davon)
|
11
|
+
# value: aktueller Wert für diesen Filter (String oder Hash)
|
12
|
+
def initialize filter, value=nil
|
13
|
+
@filter = filter
|
14
|
+
@value = value
|
15
|
+
end
|
16
|
+
|
17
|
+
# delegate der Methode 'render_value' an den Filter unter Nutzung des hinterlegten Wertes
|
18
|
+
def render_value
|
19
|
+
@filter.render_value @value
|
20
|
+
end
|
21
|
+
|
22
|
+
# delegate der Methode 'render_for_semantic_form' an den Filter unter Nutzung des hinterlegten Wertes
|
23
|
+
def render_for_semantic_form sform, context=nil, form_input_options={}
|
24
|
+
@filter.render_for_semantic_form sform, @value, context, form_input_options
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# delegate der Methode 'build_solr_query' an den Filter unter Nutzung des hinterlegten Wertes
|
29
|
+
def build_solr_query
|
30
|
+
@filter.build_solr_query @value
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module MultiSolr::RailsFormRenderHelper
|
2
|
+
|
3
|
+
|
4
|
+
# Generieren der HML-Form-Felder (input/select/..) für den angegeben Filter
|
5
|
+
# Params:
|
6
|
+
# form: das Rails-Form-Object, dieses MUSS als Object eine MultiSolr::SearchRequest-Instance haben
|
7
|
+
# filter_name: Name des Filters als Symbol (die SearchRequest-Instance im Form muss diesen Filter kennen)
|
8
|
+
# options: optionale Formular-Input-Feld-Options. Beschreibung => siehe jeweilige Beschreibung je Filter-Methode
|
9
|
+
# Diese werden i.d.R. an die Rails-Form-Methode 'text_field' weitergegeben.
|
10
|
+
#
|
11
|
+
# returns: HTML-Code des Input-Feldes als String
|
12
|
+
def render_solr_filter_for_form form, filter_name, options={}
|
13
|
+
cur_options = options.clone
|
14
|
+
search_request = form.object
|
15
|
+
filter = search_request.class.possible_filters[filter_name]
|
16
|
+
raise "unknown filter: #{filter_name}" if filter.nil?
|
17
|
+
label = cur_options.delete(:label) || filter.label
|
18
|
+
render_method = "render_#{filter.class.to_s.underscore}"
|
19
|
+
render_method.gsub!("/", '_')
|
20
|
+
render_method.gsub!("multi_solr_", '')
|
21
|
+
"<label>#{label}</label>".html_safe + send(render_method, form, filter, cur_options)
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# generiert für einen SolrFilterSimple einen input-tag vom typ text
|
26
|
+
# mit der css-class "simple"
|
27
|
+
def render_solr_filter_simple form, filter, options
|
28
|
+
add_class options, 'simple'
|
29
|
+
form.text_field "filter_#{filter.name}", options
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# generiert für einen SolrFilterSimple einen input-tag vom typ text
|
34
|
+
# mit der css-class "datepicker"
|
35
|
+
# Diese css-Klasse kann dann als jQuery-Selector für datepicker genutzt werden
|
36
|
+
def render_solr_filter_date form, filter, options
|
37
|
+
add_class options, 'datepicker'
|
38
|
+
form.text_field "filter_#{filter.name}", options
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def render_solr_filter_date_range form, filter, options
|
43
|
+
add_class options, 'datepicker'
|
44
|
+
value = form.object.send("filter_#{filter.name}")
|
45
|
+
return nil if value.blank? || !value.is_a?(Hash) || value.empty?
|
46
|
+
from = value["#{filter.name}_from"]
|
47
|
+
to = value["#{filter.name}_to"]
|
48
|
+
date_range = Struct.new("#{filter.name}_from".to_sym, "#{filter.name}_to".to_sym).new from,to
|
49
|
+
form.fields_for "filter_#{filter.name}", date_range do |fields_form|
|
50
|
+
fields_form.template.concat("<label>ab</label>".html_safe)
|
51
|
+
fields_form.template.concat(fields_form.text_field("#{filter.name}_from", options))
|
52
|
+
fields_form.template.concat("<label>bis</label>".html_safe)
|
53
|
+
fields_form.template.concat(fields_form.text_field("#{filter.name}_to", options))
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
def render_solr_filter_collection form, filter, options
|
60
|
+
add_class options, 'collection'
|
61
|
+
core_handler = options.delete(:core_handler)
|
62
|
+
context = options.delete(:context)
|
63
|
+
data = filter.collection_data(core_handler, context)
|
64
|
+
form.select "filter_#{filter.name}", data, options
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
def render_solr_filter_free_query form, filter, options
|
69
|
+
add_class options, 'free_query'
|
70
|
+
form.text_field "filter_#{filter.name}", options
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
|
77
|
+
def add_class options, css_class_name
|
78
|
+
css_class = options[:class]
|
79
|
+
css_class = css_class.nil? ? css_class_name : "#{css_class} #{css_class_name}"
|
80
|
+
options[:class] = css_class
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
end
|