multi-solr 01.01.06 → 01.02.00
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/lib/multi_solr.rb +0 -1
- data/lib/multi_solr/search_request.rb +1 -0
- data/lib/multi_solr/single_core_handler.rb +3 -0
- data/lib/multi_solr/version.rb +1 -1
- data/spec/multi_solr/single_core_handler_spec.rb +16 -1
- metadata +4 -6
- data/lib/multi_solr/base_searcher.rb +0 -393
- data/spec/multi_solr/base_searcher_spec.rb +0 -212
data/lib/multi_solr.rb
CHANGED
@@ -11,7 +11,6 @@ require 'multi_solr/solr_filter_free_query'
|
|
11
11
|
require 'multi_solr/filter_value_composite'
|
12
12
|
require 'multi_solr/search_request'
|
13
13
|
require 'multi_solr/search_result'
|
14
|
-
require 'multi_solr/base_searcher'
|
15
14
|
require 'multi_solr/single_core_handler'
|
16
15
|
require 'multi_solr/timeline_core_handler'
|
17
16
|
|
@@ -12,6 +12,7 @@ class MultiSolr::SearchRequest
|
|
12
12
|
# :mdate => {:range => true, :start => 'NOW/DAY-5Day', :end => 'NOW/DAY', :gap => '+1DAY'},
|
13
13
|
# :saison => {:stats_field => 'volumen'}}
|
14
14
|
attr_accessor :facet_params
|
15
|
+
attr_accessor :facet_prefix # optinaler Facet-Prefix bei Facetsuche. Wird als facet.prefix an Solr weitergegeben
|
15
16
|
|
16
17
|
attr_accessor :sorts # Array(String) mit den Feldnamen für die Sortierung (optional mit Sortierrichtung)
|
17
18
|
attr_accessor :stats_fields # Array(String) mit den Feldnamen für die Gesamt-Statistiken berechnet werden sollen (Summe, min, max,...)
|
@@ -344,6 +344,9 @@ class MultiSolr::SingleCoreHandler
|
|
344
344
|
# Umschalten der Facet-Ergebnisse in Array-Darstellung
|
345
345
|
# (der json.nl-Schalter wirkt auch bei Ruby siehe http://wiki.apache.org/solr/SolJSON)
|
346
346
|
solr_params['json.nl'] = 'arrarr'
|
347
|
+
if solr_search_request.facet_prefix
|
348
|
+
solr_params['facet.prefix'] = solr_search_request.facet_prefix
|
349
|
+
end
|
347
350
|
end
|
348
351
|
|
349
352
|
end
|
data/lib/multi_solr/version.rb
CHANGED
@@ -86,11 +86,16 @@ describe MultiSolr::SingleCoreHandler do
|
|
86
86
|
@request = MultiSolr::SearchRequest.new
|
87
87
|
end
|
88
88
|
|
89
|
-
it "should add force-query if context given" do
|
89
|
+
it "should add force-query if context as hash given" do
|
90
90
|
solr_params = subject.build_solr_params @request, :context => {:whs_id => 8}
|
91
91
|
solr_params[:fq].should == "whs_id:8"
|
92
92
|
end
|
93
93
|
|
94
|
+
it "should add force-query if context as string given" do
|
95
|
+
solr_params = subject.build_solr_params @request, :context => "(whs_id:8 OR whs_id:9)"
|
96
|
+
solr_params[:fq].should == "(whs_id:8 OR whs_id:9)"
|
97
|
+
end
|
98
|
+
|
94
99
|
it "should have query for all if no query specified" do
|
95
100
|
solr_params = subject.build_solr_params @request, {}
|
96
101
|
solr_params[:q].should == "*:*"
|
@@ -159,6 +164,16 @@ describe MultiSolr::SingleCoreHandler do
|
|
159
164
|
it{ @solr_params['f.gewicht.stats.facet'].should == [:sf2] }
|
160
165
|
end
|
161
166
|
|
167
|
+
context "should generate facet-params with facet.prefix if facet prefix is specified" do
|
168
|
+
before do
|
169
|
+
@request.facets = ['f1']
|
170
|
+
@request.facet_prefix = 'pre'
|
171
|
+
@solr_params = subject.build_solr_params @request, {}
|
172
|
+
end
|
173
|
+
it{ @solr_params[:facet].should be_true }
|
174
|
+
it{ @solr_params['facet.field'].should == [:f1] }
|
175
|
+
it{ @solr_params['facet.prefix'].should == 'pre' }
|
176
|
+
end
|
162
177
|
|
163
178
|
it "should set result-format if specified" do
|
164
179
|
solr_params = subject.build_solr_params @request, :result_format => 'json'
|
metadata
CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 01.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 01.02.00
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Bernd Ledig
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-06-
|
18
|
+
date: 2012-06-12 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -127,7 +127,6 @@ files:
|
|
127
127
|
- Gemfile
|
128
128
|
- Rakefile
|
129
129
|
- lib/multi_solr.rb
|
130
|
-
- lib/multi_solr/base_searcher.rb
|
131
130
|
- lib/multi_solr/filter_value_composite.rb
|
132
131
|
- lib/multi_solr/rails_form_render_helper.rb
|
133
132
|
- lib/multi_solr/search_request.rb
|
@@ -142,7 +141,6 @@ files:
|
|
142
141
|
- lib/multi_solr/version.rb
|
143
142
|
- multi-solr.gemspec
|
144
143
|
- spec/fixtures/solr-testdata.yml
|
145
|
-
- spec/multi_solr/base_searcher_spec.rb
|
146
144
|
- spec/multi_solr/search_request_spec.rb
|
147
145
|
- spec/multi_solr/search_result_spec.rb
|
148
146
|
- spec/multi_solr/single_core_handler_spec.rb
|
@@ -1,393 +0,0 @@
|
|
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
|
@@ -1,212 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe "Base-Searcher-Modul" do
|
4
|
-
|
5
|
-
|
6
|
-
subject { Class.new { include MultiSolr::BaseSearcher } }
|
7
|
-
|
8
|
-
|
9
|
-
context "core_name" do
|
10
|
-
it "should the defined core-name if set" do
|
11
|
-
subject.set_core_name 'core-set'
|
12
|
-
subject.core_name.should == 'core-set'
|
13
|
-
end
|
14
|
-
|
15
|
-
it "should use class-name if ends with Searcher" do
|
16
|
-
sample_searcher = Class.new
|
17
|
-
Object.const_set 'SampleSearcher', sample_searcher
|
18
|
-
sample_searcher.send :include, MultiSolr::BaseSearcher
|
19
|
-
sample_searcher.core_name.should == 'core-sample'
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should use local (instance) core-name if set" do
|
23
|
-
searcher = subject.new
|
24
|
-
searcher.core_name = 'test-core'
|
25
|
-
searcher.core_name.should == 'test-core'
|
26
|
-
searcher.class.core_name == 'core-default'
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
context "cached_list_possible_values" do
|
32
|
-
it "should get cached value if exist" do
|
33
|
-
fieldname = :test; context = :test_context1
|
34
|
-
value = "test-value"
|
35
|
-
MultiSolr.cache.write("solr-#{subject.core_name}-#{context}-#{fieldname}-values", value)
|
36
|
-
subject.cached_list_possible_values(fieldname, context).should == value
|
37
|
-
end
|
38
|
-
|
39
|
-
it "should call 'list_possible_values' if no cached value exist" do
|
40
|
-
fieldname = :test; context = :test_context2
|
41
|
-
value = "test-value"
|
42
|
-
subject.should_receive(:list_possible_values).with(fieldname, context, nil) do
|
43
|
-
value
|
44
|
-
end
|
45
|
-
subject.cached_list_possible_values(fieldname, context).should == value
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
|
50
|
-
context "list_possible_values" do
|
51
|
-
|
52
|
-
it "should for field p1 an Array with right sortert Strings" do
|
53
|
-
facet_searcher_mock = double :searcher
|
54
|
-
result = double :solr_result
|
55
|
-
result.stub(:facet_counts).and_return('p1' => [['schuhe', 11], ['hosen', 2]])
|
56
|
-
facet_searcher_mock.stub(:execute).and_return(result)
|
57
|
-
subject.should_receive(:new).and_return(facet_searcher_mock)
|
58
|
-
subject.list_possible_values(:p1).should == ['hosen', 'schuhe']
|
59
|
-
end
|
60
|
-
|
61
|
-
it "should for field p2 an Array with sortet Integers" do
|
62
|
-
facet_searcher_mock = double :searcher
|
63
|
-
result = double :solr_result
|
64
|
-
result.stub(:facet_counts).and_return('p2' => [['2233', 2], ['11', 3]])
|
65
|
-
facet_searcher_mock.stub(:execute).and_return(result)
|
66
|
-
subject.should_receive(:new).and_return(facet_searcher_mock)
|
67
|
-
subject.list_possible_values(:p2).should == [11, 2233] # Int-Strings sollten nach int konvertiert sein
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
context "solr_connection" do
|
72
|
-
it "should raise exception if no solr_url set" do
|
73
|
-
expect{ subject.solr_connection }.to raise_error
|
74
|
-
end
|
75
|
-
|
76
|
-
it "should connect with solr-url + core-name" do
|
77
|
-
subject.set_solr_url 'http://localhost/solr'
|
78
|
-
RSolr.should_receive(:connect) do |options|
|
79
|
-
options # zum Test die options selbst wieder zurück liefern
|
80
|
-
end
|
81
|
-
subject.solr_connection[:url].should == 'http://localhost/solr/core-default'
|
82
|
-
end
|
83
|
-
|
84
|
-
it "should use local (instance) core-name if set" do
|
85
|
-
subject.set_solr_url 'http://localhost/solr'
|
86
|
-
RSolr.should_receive(:connect) do |options|
|
87
|
-
options # zum Test die options selbst wieder zurück liefern
|
88
|
-
end
|
89
|
-
searcher = subject.new
|
90
|
-
searcher.core_name = 'test_11'
|
91
|
-
searcher.solr_connection[:url].should == 'http://localhost/solr/test_11'
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
context "execute" do
|
98
|
-
before do
|
99
|
-
@request = MultiSolr::SearchRequest.new
|
100
|
-
@searcher = subject.new
|
101
|
-
end
|
102
|
-
|
103
|
-
it "should parse result if result-format is 'ruby'" do
|
104
|
-
rsolr_mock = double('rsolr')
|
105
|
-
rsolr_mock.should_receive(:get).and_return({})
|
106
|
-
@searcher.should_receive(:solr_connection).and_return(rsolr_mock)
|
107
|
-
result = @searcher.execute @request
|
108
|
-
result.should be_a(MultiSolr::SearchResult)
|
109
|
-
end
|
110
|
-
|
111
|
-
it "should not parse result if result-format is not 'ruby'" do
|
112
|
-
@searcher.result_format = 'json'
|
113
|
-
result_mock = "RAW"
|
114
|
-
rsolr_mock = double('rsolr')
|
115
|
-
rsolr_mock.should_receive(:get).and_return(result_mock)
|
116
|
-
@searcher.should_receive(:solr_connection).and_return(rsolr_mock)
|
117
|
-
result = @searcher.execute @request
|
118
|
-
result.should == result_mock
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
context "build_solr_params" do
|
125
|
-
before do
|
126
|
-
@request = MultiSolr::SearchRequest.new
|
127
|
-
@searcher = subject.new
|
128
|
-
end
|
129
|
-
|
130
|
-
it "should add score force-query if context given" do
|
131
|
-
solr_params = @searcher.build_solr_params @request, :whs_id => 8
|
132
|
-
solr_params[:fq].should == "whs_id:8"
|
133
|
-
end
|
134
|
-
|
135
|
-
it "should have query for all if no query specified" do
|
136
|
-
solr_params = @searcher.build_solr_params @request
|
137
|
-
solr_params[:q].should == "*:*"
|
138
|
-
end
|
139
|
-
|
140
|
-
|
141
|
-
it "should use query-params builded by search request" do
|
142
|
-
@request.should_receive(:build_query).and_return('lkz:1234')
|
143
|
-
solr_params = @searcher.build_solr_params @request
|
144
|
-
solr_params[:q].should == "lkz:1234"
|
145
|
-
end
|
146
|
-
|
147
|
-
it "should add score field to fieldlist if '_val_' in query (function query)" do
|
148
|
-
@request.should_receive(:build_query).and_return('lkz:1234 _val_:"product(menge,volumen)')
|
149
|
-
solr_params = @searcher.build_solr_params @request
|
150
|
-
@searcher.fieldlist.should == "*,score"
|
151
|
-
solr_params[:fl].should == "*,score"
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should use sort if specified" do
|
155
|
-
@request.sorts = ['s1', 's2 desc']
|
156
|
-
solr_params = @searcher.build_solr_params @request
|
157
|
-
solr_params[:sort].should == 's1 asc,s2 desc'
|
158
|
-
end
|
159
|
-
|
160
|
-
context "should generate facet-params if simple facet fields specified" do
|
161
|
-
before do
|
162
|
-
@request.facets = ['f1', 'f2']
|
163
|
-
@solr_params = @searcher.build_solr_params @request
|
164
|
-
end
|
165
|
-
it{ @solr_params[:facet].should be_true }
|
166
|
-
it{ @solr_params['facet.field'].should == [:f1, :f2] }
|
167
|
-
end
|
168
|
-
|
169
|
-
context "should generate facet-params if facet fields specified" do
|
170
|
-
before do
|
171
|
-
@request.facets = ['f1', 'f2', 'f3']
|
172
|
-
@request.facet_params = {:f2 => {:limit => 1000, :sort => :index},
|
173
|
-
:f3 => {:range => true, :start => 'NOW/DAY-2DAY'}}
|
174
|
-
@solr_params = @searcher.build_solr_params @request
|
175
|
-
end
|
176
|
-
it{ @solr_params[:facet].should be_true }
|
177
|
-
it{ @solr_params['facet.field'].should == [:f1, :f2] }
|
178
|
-
it{ @solr_params['f.f2.facet.limit'].should == 1000 }
|
179
|
-
it{ @solr_params['f.f2.facet.sort'].to_s.should == 'index' }
|
180
|
-
it{ @solr_params['facet.range'].should == [:f3] }
|
181
|
-
it{ @solr_params['f.f3.facet.range.start'].should == 'NOW/DAY-2DAY' }
|
182
|
-
it{ @solr_params['f.f3.facet.range.end'].should == 'NOW/DAY' }
|
183
|
-
it{ @solr_params['f.f3.facet.range.gap'].should == '+1DAY' }
|
184
|
-
it{ @solr_params['json.nl'].should == 'arrarr' }
|
185
|
-
end
|
186
|
-
|
187
|
-
context "should generate stats-facets if facet-params have stats-field specified" do
|
188
|
-
before do
|
189
|
-
@request.facets = ['sf1', 'sf2']
|
190
|
-
@request.stats_fields = [:menge]
|
191
|
-
@request.facet_params = {:sf1 => {:stats_field => 'menge'},
|
192
|
-
:sf2 => {:stats_field => ['volumen', 'gewicht', 'menge']}}
|
193
|
-
@solr_params = @searcher.build_solr_params @request
|
194
|
-
# puts @solr_params.inspect
|
195
|
-
end
|
196
|
-
it{ @solr_params[:facet].should be_nil }
|
197
|
-
it{ @solr_params[:stats].should be_true }
|
198
|
-
it{ @solr_params['stats.field'].should == ['menge', 'volumen', 'gewicht'] }
|
199
|
-
it{ @solr_params['f.menge.stats.facet'].should == [:sf1, :sf2] }
|
200
|
-
it{ @solr_params['f.volumen.stats.facet'].should == [:sf2] }
|
201
|
-
it{ @solr_params['f.gewicht.stats.facet'].should == [:sf2] }
|
202
|
-
end
|
203
|
-
|
204
|
-
|
205
|
-
it "should set result-format to in searcher specified format" do
|
206
|
-
@searcher.result_format = 'json'
|
207
|
-
solr_params = @searcher.build_solr_params @request
|
208
|
-
solr_params[:wt].should == 'json'
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
end
|