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
@@ -0,0 +1,212 @@
|
|
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
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MultiSolr::SearchRequest do
|
4
|
+
|
5
|
+
context "define_filter" do
|
6
|
+
|
7
|
+
TEST_FILTER = {
|
8
|
+
:simple_sample => {},
|
9
|
+
:collection_sample => {:type => :collection},
|
10
|
+
:date_sample => {:type => :date},
|
11
|
+
:date_range_sample => {:type => :date_range},
|
12
|
+
:free_sample => {:type => :free_query},
|
13
|
+
}
|
14
|
+
|
15
|
+
subject do
|
16
|
+
sr_class = Class.new(MultiSolr::SearchRequest)
|
17
|
+
# die Test-Filter definieren
|
18
|
+
TEST_FILTER.each do |filtername, options|
|
19
|
+
sr_class.define_filter filtername, options.clone
|
20
|
+
end
|
21
|
+
sr_class
|
22
|
+
end
|
23
|
+
|
24
|
+
context "class behaviour" do
|
25
|
+
|
26
|
+
TEST_FILTER.each do |filtername, options|
|
27
|
+
type = (options && options[:type]) || :simple
|
28
|
+
it "should have '#{filtername}' as filter from type #{type}" do
|
29
|
+
filter_class = MultiSolr::SearchRequest::BASE_FILTER_MAP[type]
|
30
|
+
filter = subject.possible_filters[filtername]
|
31
|
+
filter.should be_a(filter_class)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should have define filter getter/setter-methods" do
|
35
|
+
r = subject.new
|
36
|
+
r.should be_respond_to("filter_#{filtername}")
|
37
|
+
r.should be_respond_to("filter_#{filtername}=")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end # of context "class behaviour"
|
41
|
+
|
42
|
+
|
43
|
+
end # of context "define_filter"
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MultiSolr::SearchResult do
|
4
|
+
|
5
|
+
SAMPLE_SOLR_RESULT = {
|
6
|
+
'responseHeader'=>{
|
7
|
+
'status'=>0,'QTime'=>61,
|
8
|
+
'params'=>{'facet.missing'=>'true','facet'=>'true','facet.mincount'=>'1','q'=>'*:*','facet.range.start'=>'2011-10-01T00:00:00Z','facet.range'=>'movement_date','facet.range.end'=>'2011-10-11T00:00:00Z','facet.range.gap'=>'+1DAY','facet.field'=>'movement_code','wt'=>'ruby','fq'=>'lager_id:8','rows'=>'3'}
|
9
|
+
},
|
10
|
+
'response'=>{
|
11
|
+
'numFound'=>2101,'start'=>0,
|
12
|
+
'docs'=>[
|
13
|
+
{'movement_code'=>129,'firma_nr'=>8,'transaction_id'=>3439846077,'groesse'=>'0','paletten_no'=>'C252935055','container_no'=>'C252935065','movement_date'=>'2011-08-01T14:03:04Z','artikelnr'=>'891454','menge'=>1,'lagerort'=>'1.0.15.066.4.0','id'=>649970561,'lager_id'=>8,'teile_nr'=>1,'type_code'=>2},
|
14
|
+
{'movement_code'=>129,'firma_nr'=>8,'transaction_id'=>3439846077,'groesse'=>'0','paletten_no'=>'C252935055','container_no'=>'C252935066','movement_date'=>'2011-08-01T14:03:04Z','artikelnr'=>'891454','menge'=>1,'lagerort'=>'1.0.15.066.4.0','id'=>649970562,'lager_id'=>8,'teile_nr'=>2,'type_code'=>2},
|
15
|
+
{'movement_code'=>129,'firma_nr'=>8,'transaction_id'=>3439846077,'groesse'=>'0','paletten_no'=>'C252935055','container_no'=>'C252935067','movement_date'=>'2011-08-01T14:03:04Z','artikelnr'=>'891454','menge'=>1,'lagerort'=>'1.0.15.066.4.0','id'=>649970563,'lager_id'=>8,'teile_nr'=>2,'type_code'=>2}
|
16
|
+
]
|
17
|
+
},
|
18
|
+
'facet_counts'=>{
|
19
|
+
'facet_queries'=>{},
|
20
|
+
'facet_fields'=>{
|
21
|
+
'movement_code'=>[['109',1088651],['33',939104],['105',617888],['29',329941],['158',128853],
|
22
|
+
['157',125759],['272',103530],['135',103011],['101',79111],[nil,0]]
|
23
|
+
},
|
24
|
+
'facet_dates'=>{},
|
25
|
+
'facet_ranges'=>{'movement_date'=>{'counts'=> [ ['2011-10-01T00:00:00Z',7910],
|
26
|
+
['2011-10-04T00:00:00Z',59650],
|
27
|
+
['2011-10-05T00:00:00Z',57882],
|
28
|
+
['2011-10-06T00:00:00Z',59728],
|
29
|
+
['2011-10-07T00:00:00Z',67143],
|
30
|
+
['2011-10-08T00:00:00Z',8721],
|
31
|
+
['2011-10-10T00:00:00Z',60442]],
|
32
|
+
'gap'=>'+1DAY','start'=>'2011-10-01T00:00:00Z','end'=>'2011-10-11T00:00:00Z'}
|
33
|
+
}
|
34
|
+
},
|
35
|
+
'stats'=>{
|
36
|
+
'stats_fields'=>{
|
37
|
+
'volumen'=>{'min'=>0.0, 'max'=>1350.0, 'count'=>256039, 'missing'=>0, 'sum'=>7741425.599999999, 'sumOfSquares'=>1.33107281946E9, 'mean'=>30.235337585289734, 'stddev'=>65.45649169441819,
|
38
|
+
'facets'=>{
|
39
|
+
'saison'=>{
|
40
|
+
'125'=>{'min'=>0.0, 'max'=>1296.0, 'count'=>161440, 'missing'=>0, 'sum'=>5462257.3999999985, 'sumOfSquares'=>1.08454124544E9, 'mean'=>33.83459737363726, 'stddev'=>74.65370742839168},
|
41
|
+
'121'=>{'min'=>1.0, 'max'=>27.0, 'count'=>740, 'missing'=>0, 'sum'=>10592.9, 'sumOfSquares'=>161604.85, 'mean'=>14.314729729729729, 'stddev'=>3.6731018490414336}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
},
|
45
|
+
'menge'=>{'min'=>1.0, 'max'=>62.0, 'count'=>256039, 'missing'=>0, 'sum'=>385627.0, 'sumOfSquares'=>3057757.0, 'mean'=>1.5061260198641613, 'stddev'=>3.1103321535761506,
|
46
|
+
'facets'=>{
|
47
|
+
'saison'=>{
|
48
|
+
'125'=>{'min'=>1.0, 'max'=>62.0, 'count'=>161440, 'missing'=>0, 'sum'=>271215.0, 'sumOfSquares'=>2532609.0, 'mean'=>1.6799739841427155, 'stddev'=>3.5868349271772577},
|
49
|
+
'121'=>{'min'=>1.0, 'max'=>1.0, 'count'=>740, 'missing'=>0, 'sum'=>740.0, 'sumOfSquares'=>740.0, 'mean'=>1.0, 'stddev'=>0.0}
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
|
57
|
+
context "non grouping result" do
|
58
|
+
before(:all) do
|
59
|
+
@search_result = MultiSolr::SearchResult.new SAMPLE_SOLR_RESULT, MultiSolr::SearchRequest.new, nil
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should set the correct hits" do
|
63
|
+
@search_result.hits.should == 2101
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should set the correct data_rows" do
|
67
|
+
@search_result.data_rows.should have(3).entries
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should set the correct facet fields" do
|
71
|
+
@search_result.facet_fields.should have(1).entries
|
72
|
+
@search_result.facet_fields['movement_code'].should have(10).entries
|
73
|
+
@search_result.facet_fields['movement_code'].first.should == ['109',1088651]
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
it "should set the correct facet ranges" do
|
78
|
+
@search_result.facet_ranges.should have(1).entries
|
79
|
+
@search_result.facet_ranges['movement_date']['counts'].should have(7).entries
|
80
|
+
@search_result.facet_ranges['movement_date']['counts'].first.should == ['2011-10-01T00:00:00Z',7910]
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
it "should have global stats" do
|
85
|
+
stats = @search_result.stats
|
86
|
+
stats.should be_a(Hash)
|
87
|
+
stats['volumen'].should be_a(Hash)
|
88
|
+
stats['menge'].should be_a(Hash)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should have facet stats" do
|
92
|
+
stats_facets = @search_result.stats_facets
|
93
|
+
stats_facets.should be_a(Hash)
|
94
|
+
saison_facet_stats = stats_facets['saison']
|
95
|
+
saison_facet_stats.should be_a(Hash)
|
96
|
+
saison_121 = saison_facet_stats['121']
|
97
|
+
saison_121.should be_a(Hash)
|
98
|
+
saison_121['menge']['sum'].should > 100
|
99
|
+
saison_121['volumen']['sum'].should > 100
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
context "Page-Data" do
|
105
|
+
before(:all) do
|
106
|
+
@search_result = MultiSolr::SearchResult.new SAMPLE_SOLR_RESULT, MultiSolr::SearchRequest.new(:page => 2, :page_size => 100), nil
|
107
|
+
end
|
108
|
+
|
109
|
+
it {@search_result.page.should == 2}
|
110
|
+
it {@search_result.total_pages.should == 22}
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
@@ -0,0 +1,169 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MultiSolr::SingleCoreHandler do
|
4
|
+
|
5
|
+
subject{ MultiSolr::SingleCoreHandler.new SolrTestdataProvider::SOLR_TEST_INSTANCE_URL, "core-01" }
|
6
|
+
|
7
|
+
context "cached_list_possible_values" do
|
8
|
+
it "should get cached value if exist" do
|
9
|
+
fieldname = :test; context = :test_context1
|
10
|
+
value = "test-value"
|
11
|
+
MultiSolr.cache.write("solr-#{subject.core_name}-#{context}-#{fieldname}-values", value)
|
12
|
+
subject.cached_list_possible_values(fieldname, context).should == value
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should call 'list_possible_values' if no cached value exist" do
|
16
|
+
fieldname = :test; context = :test_context2
|
17
|
+
value = "test-value"
|
18
|
+
subject.should_receive(:list_possible_values).with(fieldname, context) do
|
19
|
+
value
|
20
|
+
end
|
21
|
+
subject.cached_list_possible_values(fieldname, context).should == value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
context "list_possible_values" do
|
27
|
+
|
28
|
+
it "should for field p1 an Array with sorted Strings" do
|
29
|
+
result = double :solr_result
|
30
|
+
result.stub(:facet_counts).and_return('p1' => [['schuhe', 11], ['hosen', 2]])
|
31
|
+
subject.stub(:search).and_return(result)
|
32
|
+
subject.list_possible_values(:p1).should == ['hosen', 'schuhe']
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should for field p2 an Array with sortet Integers" do
|
36
|
+
result = double :solr_result
|
37
|
+
result.stub(:facet_counts).and_return('p2' => [['2233', 2], ['11', 3]])
|
38
|
+
subject.stub(:search).and_return(result)
|
39
|
+
subject.list_possible_values(:p2).should == [11, 2233] # Int-Strings sollten nach int konvertiert sein
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "solr_connection" do
|
44
|
+
it "should raise exception if no solr_url set" do
|
45
|
+
expect{ MultiSolr::SingleCoreHandler.new nil, nil }.to raise_error
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should connect with solr-url + core-name" do
|
49
|
+
RSolr.should_receive(:connect) do |options|
|
50
|
+
options # zum Test die options selbst wieder zurück liefern
|
51
|
+
end
|
52
|
+
subject.solr_connection[:url].should == "#{SolrTestdataProvider::SOLR_TEST_INSTANCE_URL}/core-01"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
|
59
|
+
context "search" do
|
60
|
+
before do
|
61
|
+
@request = MultiSolr::SearchRequest.new
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should parse result if result-format is 'ruby'" do
|
65
|
+
rsolr_mock = double('rsolr')
|
66
|
+
rsolr_mock.should_receive(:get).and_return({})
|
67
|
+
subject.should_receive(:solr_connection).and_return(rsolr_mock)
|
68
|
+
result = subject.search @request
|
69
|
+
result.should be_a(MultiSolr::SearchResult)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should not parse result if result-format is not 'ruby'" do
|
73
|
+
result_mock = "RAW"
|
74
|
+
rsolr_mock = double('rsolr')
|
75
|
+
rsolr_mock.should_receive(:get).and_return(result_mock)
|
76
|
+
subject.should_receive(:solr_connection).and_return(rsolr_mock)
|
77
|
+
result = subject.search @request, :result_format => 'json'
|
78
|
+
result.should == result_mock
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
context "build_solr_params" do
|
85
|
+
before do
|
86
|
+
@request = MultiSolr::SearchRequest.new
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should add force-query if context given" do
|
90
|
+
solr_params = subject.build_solr_params @request, :context => {:whs_id => 8}
|
91
|
+
solr_params[:fq].should == "whs_id:8"
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should have query for all if no query specified" do
|
95
|
+
solr_params = subject.build_solr_params @request, {}
|
96
|
+
solr_params[:q].should == "*:*"
|
97
|
+
end
|
98
|
+
|
99
|
+
|
100
|
+
it "should use query-params builded by search request" do
|
101
|
+
@request.should_receive(:build_query).and_return('lkz:1234')
|
102
|
+
solr_params = subject.build_solr_params @request, {}
|
103
|
+
solr_params[:q].should == "lkz:1234"
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should add score field to fieldlist if '_val_' in query (function query)" do
|
107
|
+
@request.should_receive(:build_query).and_return('lkz:1234 _val_:"product(menge,volumen)')
|
108
|
+
solr_params = subject.build_solr_params @request, {}
|
109
|
+
solr_params[:fl].should == "*,score"
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should use sort if specified" do
|
113
|
+
@request.sorts = ['s1', 's2 desc']
|
114
|
+
solr_params = subject.build_solr_params @request, {}
|
115
|
+
solr_params[:sort].should == 's1 asc,s2 desc'
|
116
|
+
end
|
117
|
+
|
118
|
+
context "should generate facet-params if simple facet fields specified" do
|
119
|
+
before do
|
120
|
+
@request.facets = ['f1', 'f2']
|
121
|
+
@solr_params = subject.build_solr_params @request, {}
|
122
|
+
end
|
123
|
+
it{ @solr_params[:facet].should be_true }
|
124
|
+
it{ @solr_params['facet.field'].should == [:f1, :f2] }
|
125
|
+
end
|
126
|
+
|
127
|
+
context "should generate facet-params if facet fields specified" do
|
128
|
+
before do
|
129
|
+
@request.facets = ['f1', 'f2', 'f3']
|
130
|
+
@request.facet_params = {:f2 => {:limit => 1000, :sort => :index},
|
131
|
+
:f3 => {:range => true, :start => 'NOW/DAY-2DAY'}}
|
132
|
+
@solr_params = subject.build_solr_params @request, {}
|
133
|
+
end
|
134
|
+
it{ @solr_params[:facet].should be_true }
|
135
|
+
it{ @solr_params['facet.field'].should == [:f1, :f2] }
|
136
|
+
it{ @solr_params['f.f2.facet.limit'].should == 1000 }
|
137
|
+
it{ @solr_params['f.f2.facet.sort'].to_s.should == 'index' }
|
138
|
+
it{ @solr_params['facet.range'].should == [:f3] }
|
139
|
+
it{ @solr_params['f.f3.facet.range.start'].should == 'NOW/DAY-2DAY' }
|
140
|
+
it{ @solr_params['f.f3.facet.range.end'].should == 'NOW/DAY' }
|
141
|
+
it{ @solr_params['f.f3.facet.range.gap'].should == '+1DAY' }
|
142
|
+
it{ @solr_params['json.nl'].should == 'arrarr' }
|
143
|
+
end
|
144
|
+
|
145
|
+
context "should generate stats-facets if facet-params have stats-field specified" do
|
146
|
+
before do
|
147
|
+
@request.facets = ['sf1', 'sf2']
|
148
|
+
@request.stats_fields = [:menge]
|
149
|
+
@request.facet_params = {:sf1 => {:stats_field => 'menge'},
|
150
|
+
:sf2 => {:stats_field => ['volumen', 'gewicht', 'menge']}}
|
151
|
+
@solr_params = subject.build_solr_params @request, {}
|
152
|
+
# puts @solr_params.inspect
|
153
|
+
end
|
154
|
+
it{ @solr_params[:facet].should be_nil }
|
155
|
+
it{ @solr_params[:stats].should be_true }
|
156
|
+
it{ @solr_params['stats.field'].should == ['menge', 'volumen', 'gewicht'] }
|
157
|
+
it{ @solr_params['f.menge.stats.facet'].should == [:sf1, :sf2] }
|
158
|
+
it{ @solr_params['f.volumen.stats.facet'].should == [:sf2] }
|
159
|
+
it{ @solr_params['f.gewicht.stats.facet'].should == [:sf2] }
|
160
|
+
end
|
161
|
+
|
162
|
+
|
163
|
+
it "should set result-format if specified" do
|
164
|
+
solr_params = subject.build_solr_params @request, :result_format => 'json'
|
165
|
+
solr_params[:wt].should == 'json'
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe MultiSolr::TimelineCoreHandler do
|
4
|
+
|
5
|
+
init_test_solr
|
6
|
+
|
7
|
+
subject do
|
8
|
+
MultiSolr::TimelineCoreHandler.new SolrTestdataProvider::SOLR_TEST_INSTANCE_URL, 'core', MultiSolr::SingleCoreHandler
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should list cores" do
|
12
|
+
subject.list_cores.should == ['core-01', 'core-02']
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
it "should get correct last_core_name" do
|
17
|
+
subject.last_core_name.should == 'core-02'
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
context "create_single_core_handler" do
|
22
|
+
|
23
|
+
it "should create Handler with last-core-name if no core-name spezified" do
|
24
|
+
handler = subject.create_single_core_handler
|
25
|
+
handler.should be_a(MultiSolr::SingleCoreHandler)
|
26
|
+
handler.core_name.should == subject.last_core_name
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should create Handler with spezified core-name" do
|
30
|
+
handler = subject.create_single_core_handler 'core-11'
|
31
|
+
handler.core_name.should == 'core-11'
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
context "core_status" do
|
37
|
+
it "should without params get the status of all cores" do
|
38
|
+
status = subject.core_status
|
39
|
+
status.keys.should have(2).entries
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should wit params get the status of the specified core" do
|
43
|
+
status = subject.core_status 'core-01'
|
44
|
+
status['name'].should == 'core-01'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
context "create_core" do
|
50
|
+
|
51
|
+
before(:all) do
|
52
|
+
@th = subject
|
53
|
+
@new_core_name = @th.create_core
|
54
|
+
SolrTestdataProvider.load_testdata_into_solr @new_core_name
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should have timestamp aus core-name-suffix" do
|
58
|
+
@th.last_core_name.should =~ /core-#{Time.now.strftime('%Y%m%d')}.*/
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should list 3 cores" do
|
62
|
+
@th.list_cores.should have(3).entries
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should set last_core_name to new core" do
|
66
|
+
@th.last_core_name.should == @new_core_name
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should correct dataDir" do
|
70
|
+
status = @th.core_status @new_core_name
|
71
|
+
status['dataDir'].should =~ /^\/tmp\/multi-solr\/data\/#{@new_core_name}/
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
context "dataimport" do
|
77
|
+
before(:all) do
|
78
|
+
@result = subject.dataimport 'dataimport-test'
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should succesfull" do
|
82
|
+
@result.should_not be_nil
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should status for import" do
|
86
|
+
status_result = subject.dataimport 'dataimport-test', 'status'
|
87
|
+
# Der Datenimport sollte noch laufen
|
88
|
+
status_result['status'].should == 'busy'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
context "remove_core" do
|
93
|
+
before(:all) do
|
94
|
+
@th = subject
|
95
|
+
@th.remove_core 'core-01', true
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should have not core-01 in core-list" do
|
99
|
+
@th.list_cores.should_not be_include('core-01')
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should delete DataDir" do
|
103
|
+
File.exist?('/tmp/multi-solr/core-01').should be_false
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "solr_testdata_provider"
|
2
|
+
|
3
|
+
module SolrTestHelper
|
4
|
+
|
5
|
+
def init_test_solr
|
6
|
+
unless $_test_solr_started
|
7
|
+
$_test_solr_started = true
|
8
|
+
SolrTestdataProvider.start_test_solr_instance
|
9
|
+
SolrTestdataProvider.load_testdata_into_solr 'core-01'
|
10
|
+
SolrTestdataProvider.load_testdata_into_solr 'core-02'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
end
|