sphinx 0.9.10.2122 → 2.1.1.3711
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -2
- data/.travis.yml +8 -0
- data/CHANGELOG.md +71 -0
- data/Gemfile +4 -0
- data/README.md +221 -0
- data/Rakefile +40 -35
- data/lib/sphinx.rb +3 -8
- data/lib/sphinx/client.rb +223 -70
- data/lib/sphinx/constants.rb +23 -8
- data/lib/sphinx/response.rb +6 -6
- data/lib/sphinx/timeout.rb +1 -2
- data/lib/sphinx/version.rb +3 -0
- data/spec/client_response_spec.rb +77 -64
- data/spec/client_spec.rb +68 -31
- data/spec/client_validations_spec.rb +61 -7
- data/spec/fixtures/requests/default_search.dat +0 -0
- data/spec/fixtures/requests/default_search_index.dat +0 -0
- data/spec/fixtures/requests/excerpt_custom.dat +0 -0
- data/spec/fixtures/requests/excerpt_default.dat +0 -0
- data/spec/fixtures/requests/excerpt_flags.dat +0 -0
- data/spec/fixtures/requests/field_weights.dat +0 -0
- data/spec/fixtures/requests/filter.dat +0 -0
- data/spec/fixtures/requests/filter_exclude.dat +0 -0
- data/spec/fixtures/requests/filter_float_range.dat +0 -0
- data/spec/fixtures/requests/filter_float_range_exclude.dat +0 -0
- data/spec/fixtures/requests/filter_range.dat +0 -0
- data/spec/fixtures/requests/filter_range_exclude.dat +0 -0
- data/spec/fixtures/requests/filter_range_int64.dat +0 -0
- data/spec/fixtures/requests/filter_ranges.dat +0 -0
- data/spec/fixtures/requests/filters.dat +0 -0
- data/spec/fixtures/requests/filters_different.dat +0 -0
- data/spec/fixtures/requests/geo_anchor.dat +0 -0
- data/spec/fixtures/requests/group_by_attr.dat +0 -0
- data/spec/fixtures/requests/group_by_attrpair.dat +0 -0
- data/spec/fixtures/requests/group_by_day.dat +0 -0
- data/spec/fixtures/requests/group_by_day_sort.dat +0 -0
- data/spec/fixtures/requests/group_by_month.dat +0 -0
- data/spec/fixtures/requests/group_by_week.dat +0 -0
- data/spec/fixtures/requests/group_by_year.dat +0 -0
- data/spec/fixtures/requests/group_distinct.dat +0 -0
- data/spec/fixtures/requests/id_range.dat +0 -0
- data/spec/fixtures/requests/id_range64.dat +0 -0
- data/spec/fixtures/requests/index_weights.dat +0 -0
- data/spec/fixtures/requests/keywords.dat +0 -0
- data/spec/fixtures/requests/limits.dat +0 -0
- data/spec/fixtures/requests/limits_cutoff.dat +0 -0
- data/spec/fixtures/requests/limits_max.dat +0 -0
- data/spec/fixtures/requests/limits_max_cutoff.dat +0 -0
- data/spec/fixtures/requests/match_all.dat +0 -0
- data/spec/fixtures/requests/match_any.dat +0 -0
- data/spec/fixtures/requests/match_boolean.dat +0 -0
- data/spec/fixtures/requests/match_extended.dat +0 -0
- data/spec/fixtures/requests/match_extended2.dat +0 -0
- data/spec/fixtures/requests/match_fullscan.dat +0 -0
- data/spec/fixtures/requests/match_phrase.dat +0 -0
- data/spec/fixtures/requests/max_query_time.dat +0 -0
- data/spec/fixtures/requests/miltiple_queries.dat +0 -0
- data/spec/fixtures/requests/outer_select.dat +0 -0
- data/spec/fixtures/requests/override.dat +0 -0
- data/spec/fixtures/{default_search.php → requests/php/default_search.php} +1 -1
- data/spec/fixtures/{default_search_index.php → requests/php/default_search_index.php} +1 -1
- data/spec/fixtures/{excerpt_custom.php → requests/php/excerpt_custom.php} +1 -1
- data/spec/fixtures/{excerpt_default.php → requests/php/excerpt_default.php} +1 -1
- data/spec/fixtures/{excerpt_flags.php → requests/php/excerpt_flags.php} +1 -1
- data/spec/fixtures/{field_weights.php → requests/php/field_weights.php} +1 -1
- data/spec/fixtures/{filter.php → requests/php/filter.php} +1 -1
- data/spec/fixtures/{filter_exclude.php → requests/php/filter_exclude.php} +1 -1
- data/spec/fixtures/{filter_float_range.php → requests/php/filter_float_range.php} +1 -1
- data/spec/fixtures/{filter_float_range_exclude.php → requests/php/filter_float_range_exclude.php} +1 -1
- data/spec/fixtures/{filter_range.php → requests/php/filter_range.php} +1 -1
- data/spec/fixtures/{filter_range_exclude.php → requests/php/filter_range_exclude.php} +1 -1
- data/spec/fixtures/{filter_range_int64.php → requests/php/filter_range_int64.php} +1 -1
- data/spec/fixtures/{filter_ranges.php → requests/php/filter_ranges.php} +1 -1
- data/spec/fixtures/{filters.php → requests/php/filters.php} +1 -1
- data/spec/fixtures/{filters_different.php → requests/php/filters_different.php} +1 -1
- data/spec/fixtures/{geo_anchor.php → requests/php/geo_anchor.php} +1 -1
- data/spec/fixtures/{group_by_attr.php → requests/php/group_by_attr.php} +1 -1
- data/spec/fixtures/{group_by_attrpair.php → requests/php/group_by_attrpair.php} +1 -1
- data/spec/fixtures/{group_by_day.php → requests/php/group_by_day.php} +1 -1
- data/spec/fixtures/{group_by_day_sort.php → requests/php/group_by_day_sort.php} +1 -1
- data/spec/fixtures/{group_by_month.php → requests/php/group_by_month.php} +1 -1
- data/spec/fixtures/{group_by_week.php → requests/php/group_by_week.php} +1 -1
- data/spec/fixtures/{group_by_year.php → requests/php/group_by_year.php} +1 -1
- data/spec/fixtures/{group_distinct.php → requests/php/group_distinct.php} +1 -1
- data/spec/fixtures/{id_range.php → requests/php/id_range.php} +1 -1
- data/spec/fixtures/{id_range64.php → requests/php/id_range64.php} +1 -1
- data/spec/fixtures/{index_weights.php → requests/php/index_weights.php} +1 -1
- data/spec/fixtures/{keywords.php → requests/php/keywords.php} +1 -1
- data/spec/fixtures/{limits.php → requests/php/limits.php} +1 -1
- data/spec/fixtures/{limits_cutoff.php → requests/php/limits_cutoff.php} +1 -1
- data/spec/fixtures/{limits_max.php → requests/php/limits_max.php} +1 -1
- data/spec/fixtures/{limits_max_cutoff.php → requests/php/limits_max_cutoff.php} +1 -1
- data/spec/fixtures/{match_all.php → requests/php/match_all.php} +1 -1
- data/spec/fixtures/{match_any.php → requests/php/match_any.php} +1 -1
- data/spec/fixtures/{match_boolean.php → requests/php/match_boolean.php} +1 -1
- data/spec/fixtures/{match_extended.php → requests/php/match_extended.php} +1 -1
- data/spec/fixtures/{match_extended2.php → requests/php/match_extended2.php} +1 -1
- data/spec/fixtures/{match_fullscan.php → requests/php/match_fullscan.php} +1 -1
- data/spec/fixtures/{match_phrase.php → requests/php/match_phrase.php} +1 -1
- data/spec/fixtures/{max_query_time.php → requests/php/max_query_time.php} +1 -1
- data/spec/fixtures/{miltiple_queries.php → requests/php/miltiple_queries.php} +1 -1
- data/spec/fixtures/requests/php/outer_select.php +9 -0
- data/spec/fixtures/{set_override.php → requests/php/override.php} +1 -1
- data/spec/fixtures/requests/php/query_flag.php +13 -0
- data/spec/fixtures/requests/php/query_flag_after_reset.php +19 -0
- data/spec/fixtures/{ranking_bm25.php → requests/php/ranking_bm25.php} +1 -1
- data/spec/fixtures/requests/php/ranking_expr.php +9 -0
- data/spec/fixtures/{ranking_fieldmask.php → requests/php/ranking_fieldmask.php} +1 -1
- data/spec/fixtures/{ranking_matchany.php → requests/php/ranking_matchany.php} +1 -1
- data/spec/fixtures/{ranking_none.php → requests/php/ranking_none.php} +1 -1
- data/spec/fixtures/{ranking_proximity.php → requests/php/ranking_proximity.php} +1 -1
- data/spec/fixtures/{ranking_proximity_bm25.php → requests/php/ranking_proximity_bm25.php} +1 -1
- data/spec/fixtures/{ranking_sph04.php → requests/php/ranking_sph04.php} +1 -1
- data/spec/fixtures/{ranking_wordcount.php → requests/php/ranking_wordcount.php} +1 -1
- data/spec/fixtures/{retries.php → requests/php/retries.php} +1 -1
- data/spec/fixtures/{retries_delay.php → requests/php/retries_delay.php} +1 -1
- data/spec/fixtures/{select.php → requests/php/select.php} +1 -1
- data/spec/fixtures/{sort_attr_asc.php → requests/php/sort_attr_asc.php} +1 -1
- data/spec/fixtures/{sort_attr_desc.php → requests/php/sort_attr_desc.php} +1 -1
- data/spec/fixtures/{sort_expr.php → requests/php/sort_expr.php} +1 -1
- data/spec/fixtures/{sort_extended.php → requests/php/sort_extended.php} +1 -1
- data/spec/fixtures/{sort_relevance.php → requests/php/sort_relevance.php} +1 -1
- data/spec/fixtures/{sort_time_segments.php → requests/php/sort_time_segments.php} +1 -1
- data/spec/fixtures/{update_attributes.php → requests/php/update_attributes.php} +1 -1
- data/spec/fixtures/{update_attributes_mva.php → requests/php/update_attributes_mva.php} +1 -1
- data/spec/fixtures/{weights.php → requests/php/weights.php} +1 -1
- data/spec/fixtures/requests/query_flag.dat +0 -0
- data/spec/fixtures/requests/query_flag_after_reset.dat +0 -0
- data/spec/fixtures/requests/ranking_bm25.dat +0 -0
- data/spec/fixtures/requests/ranking_expr.dat +0 -0
- data/spec/fixtures/requests/ranking_fieldmask.dat +0 -0
- data/spec/fixtures/requests/ranking_matchany.dat +0 -0
- data/spec/fixtures/requests/ranking_none.dat +0 -0
- data/spec/fixtures/requests/ranking_proximity.dat +0 -0
- data/spec/fixtures/requests/ranking_proximity_bm25.dat +0 -0
- data/spec/fixtures/requests/ranking_sph04.dat +0 -0
- data/spec/fixtures/requests/ranking_wordcount.dat +0 -0
- data/spec/fixtures/requests/retries.dat +0 -0
- data/spec/fixtures/requests/retries_delay.dat +0 -0
- data/spec/fixtures/requests/select.dat +0 -0
- data/spec/fixtures/requests/sort_attr_asc.dat +0 -0
- data/spec/fixtures/requests/sort_attr_desc.dat +0 -0
- data/spec/fixtures/requests/sort_expr.dat +0 -0
- data/spec/fixtures/requests/sort_extended.dat +0 -0
- data/spec/fixtures/requests/sort_relevance.dat +0 -0
- data/spec/fixtures/requests/sort_time_segments.dat +0 -0
- data/spec/fixtures/requests/update_attributes.dat +0 -0
- data/spec/fixtures/requests/update_attributes_mva.dat +0 -0
- data/spec/fixtures/requests/weights.dat +0 -0
- data/spec/fixtures/responses/build_excerpts.dat +0 -0
- data/spec/fixtures/responses/build_keywords.dat +0 -0
- data/spec/fixtures/responses/flush_attributes.dat +0 -0
- data/spec/fixtures/responses/flush_attrs.dat +2 -0
- data/spec/fixtures/responses/open.dat +0 -0
- data/spec/fixtures/responses/open_twice.dat +0 -0
- data/spec/fixtures/responses/php/build_excerpts.php +8 -0
- data/spec/fixtures/responses/php/build_keywords.php +8 -0
- data/spec/fixtures/responses/php/flush_attributes.php +8 -0
- data/spec/fixtures/responses/php/open.php +8 -0
- data/spec/fixtures/responses/php/open_twice.php +9 -0
- data/spec/fixtures/responses/php/query.php +8 -0
- data/spec/fixtures/responses/php/query_error.php +8 -0
- data/spec/fixtures/responses/php/query_id64.php +8 -0
- data/spec/fixtures/responses/php/run_queries.php +10 -0
- data/spec/fixtures/responses/php/run_queries_error.php +9 -0
- data/spec/fixtures/responses/php/status.php +8 -0
- data/spec/fixtures/responses/php/update_attributes.php +8 -0
- data/spec/fixtures/responses/php/update_attributes_mva.php +8 -0
- data/spec/fixtures/responses/query.dat +0 -0
- data/spec/fixtures/responses/query_error.dat +0 -0
- data/spec/fixtures/responses/query_id64.dat +0 -0
- data/spec/fixtures/responses/run_queries.dat +0 -0
- data/spec/fixtures/responses/run_queries_error.dat +0 -0
- data/spec/fixtures/responses/status.dat +0 -0
- data/spec/fixtures/responses/update_attributes.dat +0 -0
- data/spec/fixtures/responses/update_attributes_mva.dat +0 -0
- data/spec/fixtures/sphinxapi.php +217 -45
- data/spec/spec_helper.rb +18 -3
- data/spec/sphinx/sphinx-id64.conf +6 -6
- data/spec/sphinx/sphinx.conf +6 -6
- data/sphinx.gemspec +19 -121
- metadata +268 -105
- data/README.rdoc +0 -243
- data/VERSION.yml +0 -5
- data/init.rb +0 -1
data/lib/sphinx/constants.rb
CHANGED
@@ -24,9 +24,6 @@ module Sphinx
|
|
24
24
|
# status command
|
25
25
|
# @private
|
26
26
|
SEARCHD_COMMAND_STATUS = 5
|
27
|
-
# query command
|
28
|
-
# @private
|
29
|
-
SEARCHD_COMMAND_QUERY = 6
|
30
27
|
# flushattrs command
|
31
28
|
# @private
|
32
29
|
SEARCHD_COMMAND_FLUSHATTRS = 7
|
@@ -37,13 +34,13 @@ module Sphinx
|
|
37
34
|
|
38
35
|
# search command version
|
39
36
|
# @private
|
40
|
-
VER_COMMAND_SEARCH =
|
37
|
+
VER_COMMAND_SEARCH = 0x11D
|
41
38
|
# excerpt command version
|
42
39
|
# @private
|
43
|
-
VER_COMMAND_EXCERPT =
|
40
|
+
VER_COMMAND_EXCERPT = 0x104
|
44
41
|
# update command version
|
45
42
|
# @private
|
46
|
-
VER_COMMAND_UPDATE =
|
43
|
+
VER_COMMAND_UPDATE = 0x103
|
47
44
|
# keywords command version
|
48
45
|
# @private
|
49
46
|
VER_COMMAND_KEYWORDS = 0x100
|
@@ -116,6 +113,8 @@ module Sphinx
|
|
116
113
|
SPH_RANK_FIELDMASK = 6
|
117
114
|
# codename SPH04, phrase proximity + bm25 + head/exact boost
|
118
115
|
SPH_RANK_SPH04 = 7
|
116
|
+
# lets you specify the ranking formula in run time
|
117
|
+
SPH_RANK_EXPR = 8
|
119
118
|
|
120
119
|
#=================================================================
|
121
120
|
# Known sort modes
|
@@ -164,8 +163,12 @@ module Sphinx
|
|
164
163
|
SPH_ATTR_BIGINT = 6
|
165
164
|
# string (binary; in-memory)
|
166
165
|
SPH_ATTR_STRING = 7
|
166
|
+
# ???
|
167
|
+
SPH_ATTR_FACTORS = 1001
|
167
168
|
# this attr has multiple values (0 or more)
|
168
|
-
SPH_ATTR_MULTI =
|
169
|
+
SPH_ATTR_MULTI = 0x40000001
|
170
|
+
# this attr has multiple 64-bit values (0 or more)
|
171
|
+
SPH_ATTR_MULTI64 = 0x40000002
|
169
172
|
|
170
173
|
#=================================================================
|
171
174
|
# Known grouping functions
|
@@ -183,7 +186,19 @@ module Sphinx
|
|
183
186
|
SPH_GROUPBY_ATTR = 4
|
184
187
|
# group by sequential attrs pair
|
185
188
|
SPH_GROUPBY_ATTRPAIR = 5
|
189
|
+
|
190
|
+
#=================================================================
|
191
|
+
# Known query flags
|
192
|
+
#=================================================================
|
193
|
+
|
194
|
+
QUERY_FLAGS = HashWithIndifferentAccess.new(
|
195
|
+
:reverse_scan => { :values => [ 0, 1 ], :index => 0 },
|
196
|
+
:sort_method => { :values => ['pq', 'kbuffer' ], :index => 1 },
|
197
|
+
:max_predicted_time => { :values => lambda { |x| x > 0 }, :index => 2 },
|
198
|
+
:boolean_simplify => { :values => [ false, true ], :index => 3 },
|
199
|
+
:idf => { :values => [ 'normalized', 'plain' ], :index => 4 }
|
200
|
+
)
|
186
201
|
end
|
187
202
|
|
188
203
|
include Constants
|
189
|
-
end
|
204
|
+
end
|
data/lib/sphinx/response.rb
CHANGED
@@ -10,17 +10,17 @@ module Sphinx
|
|
10
10
|
@position = 0
|
11
11
|
@size = response.length
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
# Gets current stream position.
|
15
15
|
def position
|
16
16
|
@position
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
# Gets response size.
|
20
20
|
def size
|
21
21
|
@size
|
22
22
|
end
|
23
|
-
|
23
|
+
|
24
24
|
# Returns <tt>true</tt> when response stream is out.
|
25
25
|
def eof?
|
26
26
|
@position >= @size
|
@@ -50,7 +50,7 @@ module Sphinx
|
|
50
50
|
@position += length
|
51
51
|
return values
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
# Get string from stream.
|
55
55
|
def get_string
|
56
56
|
length = get_int
|
@@ -59,7 +59,7 @@ module Sphinx
|
|
59
59
|
@position += length
|
60
60
|
return value
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
# Get float from stream.
|
64
64
|
def get_float
|
65
65
|
raise EOFError if @position + 4 > @size
|
@@ -68,4 +68,4 @@ module Sphinx
|
|
68
68
|
return ([uval].pack('L')).unpack('f*').first
|
69
69
|
end
|
70
70
|
end
|
71
|
-
end
|
71
|
+
end
|
data/lib/sphinx/timeout.rb
CHANGED
@@ -12,8 +12,7 @@ module Sphinx
|
|
12
12
|
require 'system_timer'
|
13
13
|
Timeout = ::SystemTimer
|
14
14
|
end
|
15
|
-
rescue LoadError
|
16
|
-
puts "[sphinx] Could not load SystemTimer gem, falling back to Ruby's slower/unsafe timeout library: #{e.message}"
|
15
|
+
rescue LoadError
|
17
16
|
require 'timeout'
|
18
17
|
Timeout = ::Timeout
|
19
18
|
end
|
@@ -6,30 +6,41 @@ describe Sphinx::Client, 'connected' do
|
|
6
6
|
before :each do
|
7
7
|
@sphinx = Sphinx::Client.new
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
|
+
def mock_sphinx_response(fixture)
|
11
|
+
response = sphinx_fixture(fixture, :response)
|
12
|
+
@sock = SphinxFakeSocket.new(response, 'rb')
|
13
|
+
servers = @sphinx.instance_variable_get(:@servers)
|
14
|
+
servers.first.stub(:get_socket => @sock)
|
15
|
+
end
|
16
|
+
|
10
17
|
context 'in Query method' do
|
11
18
|
it 'should parse response' do
|
19
|
+
mock_sphinx_response('query')
|
12
20
|
result = @sphinx.Query('wifi', 'test1')
|
13
21
|
validate_results_wifi(result)
|
14
22
|
end
|
15
23
|
|
16
24
|
it 'should process 64-bit keys' do
|
25
|
+
mock_sphinx_response('query_id64')
|
17
26
|
result = @sphinx.Query('wifi', 'test2')
|
18
|
-
result['total_found'].should
|
19
|
-
result['matches'].length.should
|
20
|
-
result['matches'][0]['id'].should
|
21
|
-
result['matches'][1]['id'].should
|
22
|
-
result['matches'][2]['id'].should
|
27
|
+
result['total_found'].should eq(3)
|
28
|
+
result['matches'].length.should eq(3)
|
29
|
+
result['matches'][0]['id'].should eq(4294967298)
|
30
|
+
result['matches'][1]['id'].should eq(4294967299)
|
31
|
+
result['matches'][2]['id'].should eq(4294967297)
|
23
32
|
end
|
24
33
|
|
25
34
|
it 'should process errors in Query method' do
|
35
|
+
mock_sphinx_response('query_error')
|
26
36
|
@sphinx.Query('wifi', 'fakeindex').should be_false
|
27
|
-
@sphinx.GetLastError.
|
37
|
+
@sphinx.GetLastError.should =~ /unknown local index/
|
28
38
|
end
|
29
39
|
end
|
30
|
-
|
40
|
+
|
31
41
|
context 'in RunQueries method' do
|
32
42
|
it 'should parse batch-query responce' do
|
43
|
+
mock_sphinx_response('run_queries')
|
33
44
|
@sphinx.AddQuery('wifi', 'test1')
|
34
45
|
@sphinx.AddQuery('gprs', 'test1')
|
35
46
|
results = @sphinx.RunQueries
|
@@ -39,6 +50,7 @@ describe Sphinx::Client, 'connected' do
|
|
39
50
|
end
|
40
51
|
|
41
52
|
it 'should process errors in RunQueries method' do
|
53
|
+
mock_sphinx_response('run_queries_error')
|
42
54
|
@sphinx.AddQuery('wifi', 'fakeindex')
|
43
55
|
r = @sphinx.RunQueries
|
44
56
|
r[0]['error'].should_not be_empty
|
@@ -47,132 +59,133 @@ describe Sphinx::Client, 'connected' do
|
|
47
59
|
|
48
60
|
context 'in BuildExcerpts method' do
|
49
61
|
it 'should parse response' do
|
62
|
+
mock_sphinx_response('build_excerpts')
|
50
63
|
result = @sphinx.BuildExcerpts(['what the world', 'London is the capital of Great Britain'], 'test1', 'the')
|
51
|
-
result.should
|
64
|
+
result.should eq(['what <b>the</b> world', 'London is <b>the</b> capital of Great Britain'])
|
52
65
|
end
|
53
66
|
end
|
54
67
|
|
55
68
|
context 'in BuildKeywords method' do
|
56
69
|
it 'should parse response' do
|
70
|
+
mock_sphinx_response('build_keywords')
|
57
71
|
result = @sphinx.BuildKeywords('wifi gprs', 'test1', true)
|
58
|
-
result.should
|
72
|
+
result.should eq([
|
59
73
|
{ 'normalized' => 'wifi', 'tokenized' => 'wifi', 'hits' => 6, 'docs' => 3 },
|
60
74
|
{ 'normalized' => 'gprs', 'tokenized' => 'gprs', 'hits' => 1, 'docs' => 1 }
|
61
|
-
]
|
75
|
+
])
|
62
76
|
end
|
63
77
|
end
|
64
78
|
|
65
79
|
context 'in UpdateAttributes method' do
|
66
80
|
it 'should parse response' do
|
67
|
-
|
68
|
-
|
69
|
-
result['matches'][0]['attrs']['group_id'].should == 1
|
70
|
-
@sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [2] }).should == 1
|
71
|
-
result = @sphinx.Query('wifi', 'test1')
|
72
|
-
result['matches'][0]['attrs']['group_id'].should == 2
|
81
|
+
mock_sphinx_response('update_attributes')
|
82
|
+
@sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [1] }).should eq(1)
|
73
83
|
end
|
74
84
|
|
75
85
|
it 'should parse response with MVA' do
|
76
|
-
|
77
|
-
|
78
|
-
result['matches'][0]['attrs']['tags'].should == [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
79
|
-
@sphinx.UpdateAttributes('test1', ['tags'], { 2 => [[5, 6, 7, 8]] }, true).should == 1
|
80
|
-
result = @sphinx.Query('wifi', 'test1')
|
81
|
-
result['matches'][0]['attrs']['tags'].should == [5, 6, 7, 8]
|
86
|
+
mock_sphinx_response('update_attributes_mva')
|
87
|
+
@sphinx.UpdateAttributes('test1', ['tags'], { 2 => [[1, 2, 3, 4, 5, 6, 7, 8, 9]] }, true).should eq(1)
|
82
88
|
end
|
83
89
|
end
|
84
90
|
|
85
91
|
context 'in Open method' do
|
86
92
|
it 'should open socket' do
|
93
|
+
mock_sphinx_response('open')
|
87
94
|
@sphinx.Open.should be_true
|
88
95
|
socket = @sphinx.servers.first.instance_variable_get(:@socket)
|
89
|
-
socket.
|
90
|
-
socket.should be_kind_of(Sphinx::BufferedIO)
|
96
|
+
socket.should eq(@sock)
|
91
97
|
socket.close
|
92
98
|
end
|
93
|
-
|
99
|
+
|
94
100
|
it 'should produce an error when opened twice' do
|
101
|
+
mock_sphinx_response('open')
|
102
|
+
sock = @sock
|
95
103
|
@sphinx.Open.should be_true
|
104
|
+
mock_sphinx_response('open_twice')
|
96
105
|
@sphinx.Open.should be_false
|
97
|
-
@sphinx.GetLastError.should
|
98
|
-
|
106
|
+
@sphinx.GetLastError.should eq('already connected')
|
107
|
+
|
99
108
|
socket = @sphinx.servers.first.instance_variable_get(:@socket)
|
100
|
-
socket.should
|
109
|
+
socket.should eq(sock)
|
101
110
|
socket.close
|
102
111
|
end
|
103
112
|
end
|
104
|
-
|
113
|
+
|
105
114
|
context 'in Close method' do
|
106
115
|
it 'should open socket' do
|
116
|
+
mock_sphinx_response('open')
|
107
117
|
@sphinx.Open.should be_true
|
108
118
|
@sphinx.Close.should be_true
|
109
119
|
@sphinx.servers.first.instance_variable_get(:@socket).should be_nil
|
110
120
|
end
|
111
|
-
|
121
|
+
|
112
122
|
it 'should produce socket is closed' do
|
113
123
|
@sphinx.Close.should be_false
|
114
|
-
@sphinx.GetLastError.should
|
124
|
+
@sphinx.GetLastError.should eq('not connected')
|
115
125
|
@sphinx.servers.first.instance_variable_get(:@socket).should be_nil
|
116
|
-
|
126
|
+
|
127
|
+
mock_sphinx_response('open')
|
117
128
|
@sphinx.Open.should be_true
|
118
129
|
@sphinx.Close.should be_true
|
119
130
|
@sphinx.Close.should be_false
|
120
|
-
@sphinx.GetLastError.should
|
131
|
+
@sphinx.GetLastError.should eq('not connected')
|
121
132
|
@sphinx.servers.first.instance_variable_get(:@socket).should be_nil
|
122
133
|
end
|
123
134
|
end
|
124
135
|
|
125
136
|
context 'in Status method' do
|
126
137
|
it 'should parse response' do
|
138
|
+
mock_sphinx_response('status')
|
127
139
|
response = @sphinx.Status
|
128
140
|
response.should be_an(Array)
|
129
141
|
response.size.should be > 10
|
130
142
|
end
|
131
143
|
end
|
132
144
|
|
133
|
-
context 'in
|
145
|
+
context 'in FlushAttributes method' do
|
134
146
|
it 'should not raise an error' do
|
147
|
+
mock_sphinx_response('flush_attributes')
|
135
148
|
expect {
|
136
|
-
@sphinx.
|
149
|
+
@sphinx.FlushAttributes
|
137
150
|
}.to_not raise_error
|
138
151
|
end
|
139
152
|
end
|
140
153
|
|
141
154
|
def validate_results_wifi(result)
|
142
|
-
result['total_found'].should
|
143
|
-
result['matches'].length.should
|
155
|
+
result['total_found'].should eq(3)
|
156
|
+
result['matches'].length.should eq(3)
|
144
157
|
result['time'].should_not be_nil
|
145
|
-
result['attrs'].should
|
158
|
+
result['attrs'].should eq({
|
146
159
|
'group_id' => Sphinx::SPH_ATTR_INTEGER,
|
147
160
|
'created_at' => Sphinx::SPH_ATTR_TIMESTAMP,
|
148
161
|
'rating' => Sphinx::SPH_ATTR_FLOAT,
|
149
162
|
'tags' => Sphinx::SPH_ATTR_MULTI | Sphinx::SPH_ATTR_INTEGER
|
150
|
-
}
|
151
|
-
result['fields'].should
|
152
|
-
result['total'].should
|
163
|
+
})
|
164
|
+
result['fields'].should eq([ 'name', 'description' ])
|
165
|
+
result['total'].should eq(3)
|
153
166
|
result['matches'].should be_an_instance_of(Array)
|
154
167
|
|
155
|
-
result['matches'][0]['id'].should
|
156
|
-
result['matches'][0]['weight'].should
|
157
|
-
result['matches'][0]['attrs']['group_id'].should
|
158
|
-
result['matches'][0]['attrs']['created_at'].should
|
159
|
-
result['matches'][0]['attrs']['tags'].should
|
160
|
-
('%0.2f' % result['matches'][0]['attrs']['rating']).should
|
161
|
-
|
162
|
-
result['matches'][1]['id'].should
|
163
|
-
result['matches'][1]['weight'].should
|
164
|
-
result['matches'][1]['attrs']['group_id'].should
|
165
|
-
result['matches'][1]['attrs']['created_at'].should
|
166
|
-
result['matches'][1]['attrs']['tags'].should
|
167
|
-
('%0.2f' % result['matches'][1]['attrs']['rating']).should
|
168
|
-
|
169
|
-
result['matches'][2]['id'].should
|
170
|
-
result['matches'][2]['weight'].should
|
171
|
-
result['matches'][2]['attrs']['group_id'].should
|
172
|
-
result['matches'][2]['attrs']['created_at'].should
|
173
|
-
result['matches'][2]['attrs']['tags'].should
|
174
|
-
('%0.2f' % result['matches'][2]['attrs']['rating']).should
|
175
|
-
|
176
|
-
result['words'].should
|
168
|
+
result['matches'][0]['id'].should eq(2)
|
169
|
+
result['matches'][0]['weight'].should eq(2)
|
170
|
+
result['matches'][0]['attrs']['group_id'].should eq(2)
|
171
|
+
result['matches'][0]['attrs']['created_at'].should eq(1175683755)
|
172
|
+
result['matches'][0]['attrs']['tags'].should eq([5, 6, 7, 8])
|
173
|
+
('%0.2f' % result['matches'][0]['attrs']['rating']).should eq('54.85')
|
174
|
+
|
175
|
+
result['matches'][1]['id'].should eq(3)
|
176
|
+
result['matches'][1]['weight'].should eq(2)
|
177
|
+
result['matches'][1]['attrs']['group_id'].should eq(1)
|
178
|
+
result['matches'][1]['attrs']['created_at'].should eq(1175683847)
|
179
|
+
result['matches'][1]['attrs']['tags'].should eq([1, 7, 9, 10])
|
180
|
+
('%0.2f' % result['matches'][1]['attrs']['rating']).should eq('16.25')
|
181
|
+
|
182
|
+
result['matches'][2]['id'].should eq(1)
|
183
|
+
result['matches'][2]['weight'].should eq(1)
|
184
|
+
result['matches'][2]['attrs']['group_id'].should eq(1)
|
185
|
+
result['matches'][2]['attrs']['created_at'].should eq(1175683690)
|
186
|
+
result['matches'][2]['attrs']['tags'].should eq([1, 2, 3, 4])
|
187
|
+
('%0.2f' % result['matches'][2]['attrs']['rating']).should eq('13.32')
|
188
|
+
|
189
|
+
result['words'].should eq({ 'wifi' => { 'hits' => 6, 'docs' => 3 } })
|
177
190
|
end
|
178
191
|
end
|
data/spec/client_spec.rb
CHANGED
@@ -20,7 +20,7 @@ describe Sphinx::Client, 'disconnected' do
|
|
20
20
|
2.times do
|
21
21
|
cnt = 0
|
22
22
|
expect {
|
23
|
-
@sphinx.send(:with_server) { |server| cnt += 1; server.should
|
23
|
+
@sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[0]); raise Sphinx::SphinxConnectError }
|
24
24
|
}.to raise_error(Sphinx::SphinxConnectError)
|
25
25
|
cnt.should == 1
|
26
26
|
end
|
@@ -29,24 +29,24 @@ describe Sphinx::Client, 'disconnected' do
|
|
29
29
|
it 'should select server based on index' do
|
30
30
|
@sphinx.SetServers(@servers)
|
31
31
|
cnt = 0
|
32
|
-
@sphinx.send(:with_server, 0) { |server| cnt += 1; server.should
|
33
|
-
cnt.should
|
32
|
+
@sphinx.send(:with_server, 0) { |server| cnt += 1; server.should eq(@sphinx.servers[0]) }
|
33
|
+
cnt.should eq(1)
|
34
34
|
cnt = 0
|
35
|
-
@sphinx.send(:with_server, 1) { |server| cnt += 1; server.should
|
36
|
-
cnt.should
|
35
|
+
@sphinx.send(:with_server, 1) { |server| cnt += 1; server.should eq(@sphinx.servers[1]) }
|
36
|
+
cnt.should eq(1)
|
37
37
|
cnt = 0
|
38
|
-
@sphinx.send(:with_server, 2) { |server| cnt += 1; server.should
|
39
|
-
cnt.should
|
38
|
+
@sphinx.send(:with_server, 2) { |server| cnt += 1; server.should eq(@sphinx.servers[0]) }
|
39
|
+
cnt.should eq(1)
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'should select given server' do
|
43
43
|
@sphinx.SetServers(@servers)
|
44
44
|
cnt = 0
|
45
45
|
@sphinx.send(:with_server, @sphinx.servers[0]) { |server| cnt += 1; server.should == @sphinx.servers[0] }
|
46
|
-
cnt.should
|
46
|
+
cnt.should eq(1)
|
47
47
|
cnt = 0
|
48
48
|
@sphinx.send(:with_server, @sphinx.servers[1]) { |server| cnt += 1; server.should == @sphinx.servers[1] }
|
49
|
-
cnt.should
|
49
|
+
cnt.should eq(1)
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -58,36 +58,36 @@ describe Sphinx::Client, 'disconnected' do
|
|
58
58
|
it 'should raise an exception on error' do
|
59
59
|
cnt = 0
|
60
60
|
expect {
|
61
|
-
@sphinx.send(:with_server) { |server| cnt += 1; server.should
|
61
|
+
@sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[0]); raise Sphinx::SphinxConnectError }
|
62
62
|
}.to raise_error(Sphinx::SphinxConnectError)
|
63
|
-
cnt.should
|
63
|
+
cnt.should eq(3)
|
64
64
|
end
|
65
65
|
|
66
66
|
it 'should round-robin servers and raise an exception on error' do
|
67
67
|
@sphinx.SetServers(@servers)
|
68
68
|
cnt = 0
|
69
69
|
expect {
|
70
|
-
@sphinx.send(:with_server) { |server| cnt += 1; server.should
|
70
|
+
@sphinx.send(:with_server) { |server| cnt += 1; server.should eq(@sphinx.servers[(cnt - 1) % 2]); raise Sphinx::SphinxConnectError }
|
71
71
|
}.to raise_error(Sphinx::SphinxConnectError)
|
72
|
-
cnt.should
|
72
|
+
cnt.should eq(3)
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'should round-robin servers with respect to passed index and raise an exception on error' do
|
76
76
|
@sphinx.SetServers(@servers)
|
77
77
|
cnt = 0
|
78
78
|
expect {
|
79
|
-
@sphinx.send(:with_server, 1) { |server| cnt += 1; server.should
|
79
|
+
@sphinx.send(:with_server, 1) { |server| cnt += 1; server.should eq(@sphinx.servers[cnt % 2]); raise Sphinx::SphinxConnectError }
|
80
80
|
}.to raise_error(Sphinx::SphinxConnectError)
|
81
|
-
cnt.should
|
81
|
+
cnt.should eq(3)
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'should round-robin with respect to attempts number passed' do
|
85
85
|
@sphinx.SetServers(@servers)
|
86
86
|
cnt = 0
|
87
87
|
expect {
|
88
|
-
@sphinx.send(:with_server, 0, 5) { |server| cnt += 1; server.should
|
88
|
+
@sphinx.send(:with_server, 0, 5) { |server| cnt += 1; server.should eq(@sphinx.servers[(cnt - 1) % 2]); raise Sphinx::SphinxConnectError }
|
89
89
|
}.to raise_error(Sphinx::SphinxConnectError)
|
90
|
-
cnt.should
|
90
|
+
cnt.should eq(5)
|
91
91
|
end
|
92
92
|
end
|
93
93
|
end
|
@@ -110,7 +110,7 @@ describe Sphinx::Client, 'disconnected' do
|
|
110
110
|
@socket.should_receive(:read).with(4).and_return([1].pack('N'))
|
111
111
|
cnt = 0
|
112
112
|
@sphinx.send(:with_socket, @server) { |socket| cnt += 1; socket.should == @socket }
|
113
|
-
cnt.should
|
113
|
+
cnt.should eq(1)
|
114
114
|
end
|
115
115
|
|
116
116
|
it 'should raise exception when searchd protocol is not 1+' do
|
@@ -120,7 +120,7 @@ describe Sphinx::Client, 'disconnected' do
|
|
120
120
|
expect {
|
121
121
|
@sphinx.send(:with_socket, @server) { cnt += 1; }
|
122
122
|
}.to raise_error(Sphinx::SphinxConnectError, 'expected searchd protocol version 1+, got version \'0\'')
|
123
|
-
cnt.should
|
123
|
+
cnt.should eq(0)
|
124
124
|
end
|
125
125
|
|
126
126
|
it 'should handle request timeouts' do
|
@@ -130,10 +130,10 @@ describe Sphinx::Client, 'disconnected' do
|
|
130
130
|
cnt = 0
|
131
131
|
expect {
|
132
132
|
@sphinx.send(:with_socket, @server) { cnt += 1; sleep 2 }
|
133
|
-
}.to raise_error(Sphinx::SphinxResponseError, 'failed to read searchd response (msg=
|
134
|
-
cnt.should
|
133
|
+
}.to raise_error(Sphinx::SphinxResponseError, 'failed to read searchd response (msg=execution expired)')
|
134
|
+
cnt.should eq(1)
|
135
135
|
|
136
|
-
@sphinx.GetLastError.should
|
136
|
+
@sphinx.GetLastError.should eq('failed to read searchd response (msg=execution expired)')
|
137
137
|
@sphinx.IsConnectError.should be_false
|
138
138
|
end
|
139
139
|
|
@@ -144,9 +144,9 @@ describe Sphinx::Client, 'disconnected' do
|
|
144
144
|
expect {
|
145
145
|
@sphinx.send(:with_socket, @server) { cnt += 1; raise Sphinx::SphinxInternalError, 'hello' }
|
146
146
|
}.to raise_error(Sphinx::SphinxInternalError, 'hello')
|
147
|
-
cnt.should
|
147
|
+
cnt.should eq(1)
|
148
148
|
|
149
|
-
@sphinx.GetLastError.should
|
149
|
+
@sphinx.GetLastError.should eq('hello')
|
150
150
|
@sphinx.IsConnectError.should be_false
|
151
151
|
end
|
152
152
|
end
|
@@ -167,9 +167,9 @@ describe Sphinx::Client, 'disconnected' do
|
|
167
167
|
expect {
|
168
168
|
@sphinx.send(:with_socket, @server) { cnt += 1; raise Sphinx::SphinxInternalError, 'hello' }
|
169
169
|
}.to raise_error(Sphinx::SphinxInternalError, 'hello')
|
170
|
-
cnt.should
|
170
|
+
cnt.should eq(3)
|
171
171
|
|
172
|
-
@sphinx.GetLastError.should
|
172
|
+
@sphinx.GetLastError.should eq('hello')
|
173
173
|
@sphinx.IsConnectError.should be_false
|
174
174
|
end
|
175
175
|
end
|
@@ -206,7 +206,7 @@ describe Sphinx::Client, 'disconnected' do
|
|
206
206
|
@socket.should_receive(:read).with(8).and_return([Sphinx::SEARCHD_WARNING, 1, 14].pack('n2N'))
|
207
207
|
@socket.should_receive(:read).with(14).and_return([5].pack('N') + 'helloworld')
|
208
208
|
@sphinx.send(:parse_response, @socket, 1).should == 'world'
|
209
|
-
@sphinx.GetLastWarning.should
|
209
|
+
@sphinx.GetLastWarning.should eq('hello')
|
210
210
|
end
|
211
211
|
|
212
212
|
it 'should raise exception when SEARCHD_ERROR received' do
|
@@ -313,24 +313,26 @@ describe Sphinx::Client, 'disconnected' do
|
|
313
313
|
|
314
314
|
describe 'with rank' do
|
315
315
|
[ :proximity_bm25, :bm25, :none, :wordcount, :proximity, :matchany, :fieldmask, :sph04 ].each do |rank|
|
316
|
+
expr = rank == :expr ? '' : 'sum(lcs*user_weight)*1000+bm25'
|
317
|
+
|
316
318
|
it "should generate valid request for SPH_RANK_#{rank.to_s.upcase}" do
|
317
319
|
expected = sphinx_fixture("ranking_#{rank}")
|
318
320
|
@sock.should_receive(:write).with(expected)
|
319
|
-
@sphinx.SetRankingMode(Sphinx::Client.const_get("SPH_RANK_#{rank.to_s.upcase}"))
|
321
|
+
@sphinx.SetRankingMode(Sphinx::Client.const_get("SPH_RANK_#{rank.to_s.upcase}"), expr)
|
320
322
|
sphinx_safe_call { @sphinx.Query('query') }
|
321
323
|
end
|
322
324
|
|
323
325
|
it "should generate valid request for \"#{rank}\"" do
|
324
326
|
expected = sphinx_fixture("ranking_#{rank}")
|
325
327
|
@sock.should_receive(:write).with(expected)
|
326
|
-
@sphinx.SetRankingMode(rank.to_s)
|
328
|
+
@sphinx.SetRankingMode(rank.to_s, expr)
|
327
329
|
sphinx_safe_call { @sphinx.Query('query') }
|
328
330
|
end
|
329
331
|
|
330
332
|
it "should generate valid request for :#{rank}" do
|
331
333
|
expected = sphinx_fixture("ranking_#{rank}")
|
332
334
|
@sock.should_receive(:write).with(expected)
|
333
|
-
@sphinx.SetRankingMode(rank)
|
335
|
+
@sphinx.SetRankingMode(rank, expr)
|
334
336
|
sphinx_safe_call { @sphinx.Query('query') }
|
335
337
|
end
|
336
338
|
end
|
@@ -535,7 +537,7 @@ describe Sphinx::Client, 'disconnected' do
|
|
535
537
|
end
|
536
538
|
|
537
539
|
it 'should generate valid request for SetOverride' do
|
538
|
-
expected = sphinx_fixture('
|
540
|
+
expected = sphinx_fixture('override')
|
539
541
|
@sock.should_receive(:write).with(expected)
|
540
542
|
@sphinx.SetOverride('attr1', Sphinx::SPH_ATTR_INTEGER, { 10 => 20 })
|
541
543
|
@sphinx.SetOverride('attr2', Sphinx::SPH_ATTR_FLOAT, { 11 => 30.3 })
|
@@ -549,6 +551,41 @@ describe Sphinx::Client, 'disconnected' do
|
|
549
551
|
@sphinx.SetSelect('attr1, attr2')
|
550
552
|
sphinx_safe_call { @sphinx.Query('query') }
|
551
553
|
end
|
554
|
+
|
555
|
+
it 'should generate valid request for SetOuterSelect' do
|
556
|
+
expected = sphinx_fixture('outer_select')
|
557
|
+
@sock.should_receive(:write).with(expected)
|
558
|
+
@sphinx.SetOuterSelect('attr', 10, 100)
|
559
|
+
sphinx_safe_call { @sphinx.Query('query') }
|
560
|
+
end
|
561
|
+
|
562
|
+
it 'should generate valid request for SetQueryFlag' do
|
563
|
+
expected = sphinx_fixture('query_flag')
|
564
|
+
@sock.should_receive(:write).with(expected)
|
565
|
+
@sphinx.SetQueryFlag('reverse_scan', 1)
|
566
|
+
@sphinx.SetQueryFlag('sort_method', 'kbuffer')
|
567
|
+
@sphinx.SetQueryFlag('max_predicted_time', 15)
|
568
|
+
@sphinx.SetQueryFlag('boolean_simplify', true)
|
569
|
+
@sphinx.SetQueryFlag('idf', 'plain')
|
570
|
+
sphinx_safe_call { @sphinx.Query('query') }
|
571
|
+
end
|
572
|
+
|
573
|
+
it 'should generate valid request for SetQueryFlag after flag reset' do
|
574
|
+
expected = sphinx_fixture('query_flag_after_reset')
|
575
|
+
@sock.should_receive(:write).with(expected)
|
576
|
+
@sphinx.SetQueryFlag('reverse_scan', 1)
|
577
|
+
@sphinx.SetQueryFlag('sort_method', 'kbuffer')
|
578
|
+
@sphinx.SetQueryFlag('max_predicted_time', 15)
|
579
|
+
@sphinx.SetQueryFlag('boolean_simplify', true)
|
580
|
+
@sphinx.SetQueryFlag('idf', 'plain')
|
581
|
+
|
582
|
+
@sphinx.SetQueryFlag('reverse_scan', 0)
|
583
|
+
@sphinx.SetQueryFlag('sort_method', 'pq')
|
584
|
+
@sphinx.SetQueryFlag('max_predicted_time', 0)
|
585
|
+
@sphinx.SetQueryFlag('boolean_simplify', false)
|
586
|
+
@sphinx.SetQueryFlag('idf', 'normalized')
|
587
|
+
sphinx_safe_call { @sphinx.Query('query') }
|
588
|
+
end
|
552
589
|
end
|
553
590
|
|
554
591
|
context 'in RunQueries method' do
|