rlibsphinxclient 0.2.2

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.
Files changed (79) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG.rdoc +18 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.rdoc +151 -0
  5. data/Rakefile +39 -0
  6. data/VERSION +1 -0
  7. data/ext/extconf.rb +20 -0
  8. data/ext/rlibsphinxclient.i +314 -0
  9. data/ext/rlibsphinxclient_wrap.c +5931 -0
  10. data/init.rb +1 -0
  11. data/lib/sphinx.rb +22 -0
  12. data/lib/sphinx/client.rb +1070 -0
  13. data/lib/sphinx/fast_client.rb +184 -0
  14. data/lib/sphinx/request.rb +49 -0
  15. data/lib/sphinx/response.rb +69 -0
  16. data/lib/sphinx/safe_executor.rb +11 -0
  17. data/lib/sphinx/timeout.rb +9 -0
  18. data/rlibsphinxclient.gemspec +117 -0
  19. data/spec/client_response_spec.rb +135 -0
  20. data/spec/client_spec.rb +548 -0
  21. data/spec/fixtures/default_search.php +8 -0
  22. data/spec/fixtures/default_search_index.php +8 -0
  23. data/spec/fixtures/excerpt_custom.php +11 -0
  24. data/spec/fixtures/excerpt_default.php +8 -0
  25. data/spec/fixtures/excerpt_flags.php +11 -0
  26. data/spec/fixtures/field_weights.php +9 -0
  27. data/spec/fixtures/filter.php +9 -0
  28. data/spec/fixtures/filter_exclude.php +9 -0
  29. data/spec/fixtures/filter_float_range.php +9 -0
  30. data/spec/fixtures/filter_float_range_exclude.php +9 -0
  31. data/spec/fixtures/filter_range.php +9 -0
  32. data/spec/fixtures/filter_range_exclude.php +9 -0
  33. data/spec/fixtures/filter_ranges.php +10 -0
  34. data/spec/fixtures/filters.php +10 -0
  35. data/spec/fixtures/filters_different.php +13 -0
  36. data/spec/fixtures/geo_anchor.php +9 -0
  37. data/spec/fixtures/group_by_attr.php +9 -0
  38. data/spec/fixtures/group_by_attrpair.php +9 -0
  39. data/spec/fixtures/group_by_day.php +9 -0
  40. data/spec/fixtures/group_by_day_sort.php +9 -0
  41. data/spec/fixtures/group_by_month.php +9 -0
  42. data/spec/fixtures/group_by_week.php +9 -0
  43. data/spec/fixtures/group_by_year.php +9 -0
  44. data/spec/fixtures/group_distinct.php +10 -0
  45. data/spec/fixtures/id_range.php +9 -0
  46. data/spec/fixtures/id_range64.php +9 -0
  47. data/spec/fixtures/index_weights.php +9 -0
  48. data/spec/fixtures/keywords.php +8 -0
  49. data/spec/fixtures/limits.php +9 -0
  50. data/spec/fixtures/limits_cutoff.php +9 -0
  51. data/spec/fixtures/limits_max.php +9 -0
  52. data/spec/fixtures/limits_max_cutoff.php +9 -0
  53. data/spec/fixtures/match_all.php +9 -0
  54. data/spec/fixtures/match_any.php +9 -0
  55. data/spec/fixtures/match_boolean.php +9 -0
  56. data/spec/fixtures/match_extended.php +9 -0
  57. data/spec/fixtures/match_extended2.php +9 -0
  58. data/spec/fixtures/match_fullscan.php +9 -0
  59. data/spec/fixtures/match_phrase.php +9 -0
  60. data/spec/fixtures/max_query_time.php +9 -0
  61. data/spec/fixtures/miltiple_queries.php +12 -0
  62. data/spec/fixtures/ranking_bm25.php +9 -0
  63. data/spec/fixtures/ranking_none.php +9 -0
  64. data/spec/fixtures/ranking_proximity_bm25.php +9 -0
  65. data/spec/fixtures/ranking_wordcount.php +9 -0
  66. data/spec/fixtures/retries.php +9 -0
  67. data/spec/fixtures/retries_delay.php +9 -0
  68. data/spec/fixtures/sort_attr_asc.php +9 -0
  69. data/spec/fixtures/sort_attr_desc.php +9 -0
  70. data/spec/fixtures/sort_expr.php +9 -0
  71. data/spec/fixtures/sort_extended.php +9 -0
  72. data/spec/fixtures/sort_relevance.php +9 -0
  73. data/spec/fixtures/sort_time_segments.php +9 -0
  74. data/spec/fixtures/sphinxapi.php +1181 -0
  75. data/spec/fixtures/update_attributes.php +8 -0
  76. data/spec/fixtures/weights.php +9 -0
  77. data/spec/sphinx/sphinx.conf +67 -0
  78. data/spec/sphinx/sphinx_test.sql +86 -0
  79. metadata +133 -0
@@ -0,0 +1,184 @@
1
+ # = fast_client.rb - Wrapper for pure C Sphinx client API
2
+ #
3
+ # Author:: Dmytro Shteflyuk <mailto:kpumuk@kpumuk.info>.
4
+ # Copyright:: Copyright (c) 2009 Dmytro Shteflyuk
5
+ # License:: Distributes under the MIT license.
6
+ # Version:: 0.2.2
7
+ # Website:: http://kpumuk.info/projects/ror-plugins/sphinx
8
+ #
9
+ # This library is distributed under the terms of the MIT license.
10
+
11
+ # == Sphinx Client API
12
+ #
13
+ # The Sphinx Client API is used to communicate with <tt>searchd</tt>
14
+ # daemon and get search results from Sphinx.
15
+ #
16
+ # === Usage
17
+ #
18
+ # begin
19
+ # sphinx = Sphinx::FastClient.new
20
+ # result = sphinx.Query('test')
21
+ # ids = result['matches'].map { |match| match['id'] }.join(',')
22
+ # posts = Post.find :all, :conditions => "id IN (#{ids})"
23
+ #
24
+ # docs = posts.map(&:body)
25
+ # excerpts = sphinx.BuildExcerpts(docs, 'index', 'test')
26
+ # ensure
27
+ # sphinx.destroy
28
+ # end
29
+
30
+ module Sphinx
31
+
32
+ # A wrapper for pure C Sphinx client API.
33
+ class FastClient
34
+ Lib = Rlibsphinxclient
35
+
36
+ # Constructs the <tt>Sphinx::FastClient</tt> object and sets options to their default values.
37
+ def initialize
38
+ @sphinx = Lib.sphinx_create(true)
39
+ end
40
+
41
+ # Destroys all internal memory buffers. Should be called when Sphinx API is no needed.
42
+ def destroy
43
+ Lib.sphinx_destroy(@sphinx)
44
+ @sphinx = nil
45
+ end
46
+
47
+ # See Client.GetLastError for details.
48
+ def GetLastError
49
+ Lib.sphinx_error(@sphinx)
50
+ end
51
+
52
+ # See Client.GetLastWarning for details.
53
+ def GetLastWarning
54
+ Lib.sphinx_warning(@sphinx)
55
+ end
56
+
57
+ # See Client.SetServer for details.
58
+ def SetServer(host, port)
59
+ Lib.sphinx_set_server(@sphinx, host, port)
60
+ end
61
+
62
+ def SetConnectionTimeout(seconds)
63
+ Lib.sphinx_set_connect_timeout(@sphinx, seconds)
64
+ end
65
+
66
+ # See Client.SetLimits for details.
67
+ def SetLimits(offset, limit, max_matches = 0, cutoff = 0)
68
+ Lib.sphinx_set_limits(@sphinx, offset, limit, max_matches, cutoff)
69
+ end
70
+
71
+ # See Client.SetMaxQueryTime for details.
72
+ def SetMaxQueryTime(max_query_time)
73
+ Lib.sphinx_set_max_query_time(@sphinx, max_query_time)
74
+ end
75
+
76
+ # See Client.SetMatchMode for details.
77
+ def SetMatchMode(mode)
78
+ mode = Lib.const_get("SPH_MATCH_#{mode.to_s.upcase}") if mode.is_a? Symbol
79
+ Lib.sphinx_set_match_mode(@sphinx, mode)
80
+ end
81
+
82
+ # See Client.SetRankingMode for details.
83
+ def SetRankingMode(ranker)
84
+ ranker = Lib.const_get("SPH_RANK_#{ranker.to_s.upcase}") if ranker.is_a? Symbol
85
+ Lib.sphinx_set_ranking_mode(@sphinx, ranker)
86
+ end
87
+
88
+ # See Client.SetSortMode for details.
89
+ def SetSortMode(mode, sortby = '')
90
+ mode = Lib.const_get("SPH_SORT_#{mode.to_s.upcase}") if mode.is_a? Symbol
91
+ Lib.sphinx_set_sort_mode(@sphinx, mode, sortby)
92
+ end
93
+
94
+ # See Client.SetFieldWeights for details.
95
+ def SetFieldWeights(weights)
96
+ Lib.sphinx_set_field_weights(@sphinx, weights.size, weights.keys, weights.values)
97
+ end
98
+
99
+ # See Client.SetIndexWeights for details.
100
+ def SetIndexWeights(weights)
101
+ Lib.sphinx_set_index_weights(@sphinx, weights.size, weights.keys, weights.values)
102
+ end
103
+
104
+ # See Client.SetIDRange for details.
105
+ def SetIDRange(min, max)
106
+ Lib.sphinx_set_id_range(@sphinx, min, max)
107
+ end
108
+
109
+ # See Client.SetFilter for details.
110
+ def SetFilter(attribute, values, exclude = false)
111
+ Lib.sphinx_add_filter(@sphinx, attribute, values.length, values, exclude)
112
+ end
113
+
114
+ # See Client.SetFilterRange for details.
115
+ def SetFilterRange(attribute, min, max, exclude = false)
116
+ Lib.sphinx_add_filter_range(@sphinx, attribute, min, max, exclude)
117
+ end
118
+
119
+ # See Client.SetFilterFloatRange for details.
120
+ def SetFilterFloatRange(attribute, min, max, exclude = false)
121
+ Lib.sphinx_add_filter_float_range(@sphinx, attribute, min, max, exclude)
122
+ end
123
+
124
+ # See Client.SetGeoAnchor for details.
125
+ def SetGeoAnchor(attrlat, attrlong, lat, long)
126
+ Lib.sphinx_set_geoanchor(@sphinx, attrlat, attrlong, lat, long)
127
+ end
128
+
129
+ # See Client.SetGroupBy for details.
130
+ def SetGroupBy(attribute, func, groupsort = '@group desc')
131
+ Lib.sphinx_set_groupby(@sphinx, attribute, func, groupsort)
132
+ end
133
+
134
+ # See Client.SetGroupDistinct for details.
135
+ def SetGroupDistinct(attribute)
136
+ Lib.sphinx_set_groupby_distinct(@sphinx, attribute)
137
+ end
138
+
139
+ # See Client.SetRetries for details.
140
+ def SetRetries(count, delay = 0)
141
+ Lib.sphinx_set_retries(@sphinx, count, delay)
142
+ end
143
+
144
+ # See Client.ResetFilters for details.
145
+ def ResetFilters
146
+ Lib.sphinx_reset_filters(@sphinx)
147
+ end
148
+
149
+ # See Client.ResetGroupBy for details.
150
+ def ResetGroupBy
151
+ Lib.sphinx_reset_groupby(@sphinx)
152
+ end
153
+
154
+ # See Client.Query for details.
155
+ def Query(query, index = '*', comment = '')
156
+ Lib.sphinx_query(@sphinx, query, index, comment)
157
+ end
158
+
159
+ # See Client.AddQuery for details.
160
+ def AddQuery(query, index = '*', comment = '')
161
+ Lib.sphinx_add_query(@sphinx, query, index, comment)
162
+ end
163
+
164
+ # See Client.RunQueries for details.
165
+ def RunQueries
166
+ Lib.sphinx_run_queries(@sphinx)
167
+ end
168
+
169
+ # See Client.BuildExcerpts for details.
170
+ def BuildExcerpts(docs, index, words, opts = {})
171
+ Lib.sphinx_build_excerpts(@sphinx, docs.size, docs, index, words, opts)
172
+ end
173
+
174
+ # See Client.BuildKeywords for details.
175
+ def BuildKeywords(query, index, hits)
176
+ Lib.sphinx_build_keywords(@sphinx, query, index, hits)
177
+ end
178
+
179
+ # See Client.UpdateAttributes for details.
180
+ def UpdateAttributes(index, attrs, values, mva = false)
181
+ Lib.sphinx_update_attributes(@sphinx, index, attrs.size, attrs, values.size, values.keys, values.values.flatten)
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,49 @@
1
+ module Sphinx
2
+ # Pack ints, floats, strings, and arrays to internal representation
3
+ # needed by Sphinx search engine.
4
+ class Request
5
+ # Initialize new request.
6
+ def initialize
7
+ @request = ''
8
+ end
9
+
10
+ # Put int(s) to request.
11
+ def put_int(*ints)
12
+ ints.each { |i| @request << [i].pack('N') }
13
+ end
14
+
15
+ # Put 64-bit int(s) to request.
16
+ def put_int64(*ints)
17
+ ints.each { |i| @request << [i >> 32, i & ((1 << 32) - 1)].pack('NN') }
18
+ end
19
+
20
+ # Put 64-bit int(s) to request (Sphinx 0.9.9 compatible version).
21
+ def put_int64_new(*ints)
22
+ ints.each { |i| @request << [i].pack('q').reverse }
23
+ end
24
+
25
+ # Put string(s) to request (first length, then the string itself).
26
+ def put_string(*strings)
27
+ strings.each { |s| @request << [s.length].pack('N') + s }
28
+ end
29
+
30
+ # Put float(s) to request.
31
+ def put_float(*floats)
32
+ floats.each do |f|
33
+ t1 = [f].pack('f') # machine order
34
+ t2 = t1.unpack('L*').first # int in machine order
35
+ @request << [t2].pack('N')
36
+ end
37
+ end
38
+
39
+ # Put array of ints to request (first length, then the array itself)
40
+ def put_int_array(arr)
41
+ put_int arr.length, *arr
42
+ end
43
+
44
+ # Returns the entire message
45
+ def to_s
46
+ @request
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,69 @@
1
+ module Sphinx
2
+ # Unpack internal Sphinx representation of ints, floats, strings, and arrays.
3
+ # needed by Sphinx search engine.
4
+ class Response
5
+ # Initialize new request.
6
+ def initialize(response)
7
+ @response = response
8
+ @position = 0
9
+ @size = response.length
10
+ end
11
+
12
+ # Gets current stream position.
13
+ def position
14
+ @position
15
+ end
16
+
17
+ # Gets response size.
18
+ def size
19
+ @size
20
+ end
21
+
22
+ # Returns <tt>true</tt> when response stream is out.
23
+ def eof?
24
+ @position >= @size
25
+ end
26
+
27
+ # Get int from stream.
28
+ def get_int
29
+ raise EOFError if @position + 4 > @size
30
+ value = @response[@position, 4].unpack('N*').first
31
+ @position += 4
32
+ return value
33
+ end
34
+
35
+ # Get 64-bit int from stream.
36
+ def get_int64
37
+ raise EOFError if @position + 8 > @size
38
+ hi, lo = @response[@position, 8].unpack('N*N*')
39
+ @position += 8
40
+ return (hi << 32) + lo
41
+ end
42
+
43
+ # Get array of <tt>count</tt> ints from stream.
44
+ def get_ints(count)
45
+ length = 4 * count
46
+ raise EOFError if @position + length > @size
47
+ values = @response[@position, length].unpack('N*' * count)
48
+ @position += length
49
+ return values
50
+ end
51
+
52
+ # Get string from stream.
53
+ def get_string
54
+ length = get_int
55
+ raise EOFError if @position + length > @size
56
+ value = length > 0 ? @response[@position, length] : ''
57
+ @position += length
58
+ return value
59
+ end
60
+
61
+ # Get float from stream.
62
+ def get_float
63
+ raise EOFError if @position + 4 > @size
64
+ uval = @response[@position, 4].unpack('N*').first;
65
+ @position += 4
66
+ return ([uval].pack('L')).unpack('f*').first
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ module Sphinx
2
+ class SafeExecutor
3
+ def self.execute(timeout = 5, attempts = 3, &block)
4
+ Sphinx::Timeout.timeout(timeout, &block)
5
+ rescue ::Timeout::Error
6
+ attempts -= 1
7
+ raise if attempts <= 0
8
+ retry
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Sphinx
2
+ begin
3
+ require 'system_timer'
4
+ Timeout = ::SystemTimer
5
+ rescue LoadError
6
+ require 'timeout'
7
+ Timeout = ::Timeout
8
+ end
9
+ end
@@ -0,0 +1,117 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rlibsphinxclient}
8
+ s.version = "0.2.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Dmytro Shteflyuk"]
12
+ s.date = %q{2009-10-15}
13
+ s.email = %q{kpumuk@kpumuk.info}
14
+ s.extensions = ["ext/extconf.rb"]
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "CHANGELOG.rdoc",
21
+ "MIT-LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "ext/extconf.rb",
26
+ "ext/rlibsphinxclient.i",
27
+ "ext/rlibsphinxclient_wrap.c",
28
+ "init.rb",
29
+ "lib/sphinx.rb",
30
+ "lib/sphinx/client.rb",
31
+ "lib/sphinx/fast_client.rb",
32
+ "lib/sphinx/request.rb",
33
+ "lib/sphinx/response.rb",
34
+ "lib/sphinx/safe_executor.rb",
35
+ "lib/sphinx/timeout.rb",
36
+ "rlibsphinxclient.gemspec",
37
+ "spec/client_response_spec.rb",
38
+ "spec/client_spec.rb",
39
+ "spec/fixtures/default_search.php",
40
+ "spec/fixtures/default_search_index.php",
41
+ "spec/fixtures/excerpt_custom.php",
42
+ "spec/fixtures/excerpt_default.php",
43
+ "spec/fixtures/excerpt_flags.php",
44
+ "spec/fixtures/field_weights.php",
45
+ "spec/fixtures/filter.php",
46
+ "spec/fixtures/filter_exclude.php",
47
+ "spec/fixtures/filter_float_range.php",
48
+ "spec/fixtures/filter_float_range_exclude.php",
49
+ "spec/fixtures/filter_range.php",
50
+ "spec/fixtures/filter_range_exclude.php",
51
+ "spec/fixtures/filter_ranges.php",
52
+ "spec/fixtures/filters.php",
53
+ "spec/fixtures/filters_different.php",
54
+ "spec/fixtures/geo_anchor.php",
55
+ "spec/fixtures/group_by_attr.php",
56
+ "spec/fixtures/group_by_attrpair.php",
57
+ "spec/fixtures/group_by_day.php",
58
+ "spec/fixtures/group_by_day_sort.php",
59
+ "spec/fixtures/group_by_month.php",
60
+ "spec/fixtures/group_by_week.php",
61
+ "spec/fixtures/group_by_year.php",
62
+ "spec/fixtures/group_distinct.php",
63
+ "spec/fixtures/id_range.php",
64
+ "spec/fixtures/id_range64.php",
65
+ "spec/fixtures/index_weights.php",
66
+ "spec/fixtures/keywords.php",
67
+ "spec/fixtures/limits.php",
68
+ "spec/fixtures/limits_cutoff.php",
69
+ "spec/fixtures/limits_max.php",
70
+ "spec/fixtures/limits_max_cutoff.php",
71
+ "spec/fixtures/match_all.php",
72
+ "spec/fixtures/match_any.php",
73
+ "spec/fixtures/match_boolean.php",
74
+ "spec/fixtures/match_extended.php",
75
+ "spec/fixtures/match_extended2.php",
76
+ "spec/fixtures/match_fullscan.php",
77
+ "spec/fixtures/match_phrase.php",
78
+ "spec/fixtures/max_query_time.php",
79
+ "spec/fixtures/miltiple_queries.php",
80
+ "spec/fixtures/ranking_bm25.php",
81
+ "spec/fixtures/ranking_none.php",
82
+ "spec/fixtures/ranking_proximity_bm25.php",
83
+ "spec/fixtures/ranking_wordcount.php",
84
+ "spec/fixtures/retries.php",
85
+ "spec/fixtures/retries_delay.php",
86
+ "spec/fixtures/sort_attr_asc.php",
87
+ "spec/fixtures/sort_attr_desc.php",
88
+ "spec/fixtures/sort_expr.php",
89
+ "spec/fixtures/sort_extended.php",
90
+ "spec/fixtures/sort_relevance.php",
91
+ "spec/fixtures/sort_time_segments.php",
92
+ "spec/fixtures/sphinxapi.php",
93
+ "spec/fixtures/update_attributes.php",
94
+ "spec/fixtures/weights.php",
95
+ "spec/sphinx/sphinx.conf",
96
+ "spec/sphinx/sphinx_test.sql"
97
+ ]
98
+ s.homepage = %q{http://github.com/kpumuk/rlibsphinxclient}
99
+ s.rdoc_options = ["--charset=UTF-8"]
100
+ s.require_paths = ["lib"]
101
+ s.rubygems_version = %q{1.3.5}
102
+ s.summary = %q{A Ruby wrapper for pure C searchd client API library.}
103
+ s.test_files = [
104
+ "spec/client_response_spec.rb",
105
+ "spec/client_spec.rb"
106
+ ]
107
+
108
+ if s.respond_to? :specification_version then
109
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
110
+ s.specification_version = 3
111
+
112
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
113
+ else
114
+ end
115
+ else
116
+ end
117
+ end
@@ -0,0 +1,135 @@
1
+ require File.dirname(__FILE__) + '/../init'
2
+
3
+ describe 'client API library', :shared => true do
4
+ it 'should have all filters working' do
5
+ @sphinx.SetServer('localhost', 3312)
6
+ @sphinx.SetLimits(1, 100, 20, 30)
7
+ @sphinx.SetMaxQueryTime(5)
8
+ @sphinx.SetMatchMode(Sphinx::Client::SPH_MATCH_EXTENDED2)
9
+ @sphinx.SetRankingMode(Sphinx::Client::SPH_RANK_BM25)
10
+ @sphinx.SetSortMode(Sphinx::Client::SPH_SORT_RELEVANCE)
11
+ @sphinx.SetFieldWeights('group_id' => 10, 'rating' => 20)
12
+ @sphinx.SetIndexWeights('test1' => 20, 'test2' => 30)
13
+ @sphinx.SetIDRange(1, 100)
14
+ @sphinx.SetFilter('group_id', [1], true)
15
+ @sphinx.SetFilterRange('group_id', 1, 2, true)
16
+ @sphinx.SetFilterFloatRange('rating', 1, 3, true)
17
+ @sphinx.SetGroupBy('created_at', Sphinx::Client::SPH_GROUPBY_DAY)
18
+ @sphinx.SetGroupDistinct('group_id')
19
+ @sphinx.SetRetries(5, 10)
20
+ result = @sphinx.Query('wifi', 'test1')
21
+
22
+ result.should_not be_nil
23
+ end
24
+
25
+ it 'should parse response in Query method' do
26
+ result = @sphinx.Query('wifi', 'test1')
27
+ validate_results_wifi(result)
28
+ end
29
+
30
+ it 'should process 64-bit keys in Query method' do
31
+ result = @sphinx.Query('wifi', 'test2')
32
+ result['total_found'].should == 3
33
+ result['matches'].length.should == 3
34
+ result['matches'][0]['id'].should == 4294967298
35
+ result['matches'][1]['id'].should == 4294967299
36
+ result['matches'][2]['id'].should == 4294967297
37
+ end
38
+
39
+ it 'should parse batch-query responce in RunQueries method' do
40
+ @sphinx.AddQuery('wifi', 'test1')
41
+ @sphinx.AddQuery('gprs', 'test1')
42
+ results = @sphinx.RunQueries
43
+ results.should be_an(Array)
44
+ results.length.should == 2
45
+ validate_results_wifi(results[0])
46
+ end
47
+
48
+ it 'should parse response in BuildExcerpts method' do
49
+ result = @sphinx.BuildExcerpts(['what the world', 'London is the capital of Great Britain'], 'test1', 'the')
50
+ result.should == ['what <b>the</b> world', 'London is <b>the</b> capital of Great Britain']
51
+ end
52
+
53
+ it 'should parse response in BuildKeywords method' do
54
+ result = @sphinx.BuildKeywords('wifi gprs', 'test1', true)
55
+ result.should == [
56
+ { 'normalized' => 'wifi', 'tokenized' => 'wifi', 'hits' => 6, 'docs' => 3 },
57
+ { 'normalized' => 'gprs', 'tokenized' => 'gprs', 'hits' => 1, 'docs' => 1 }
58
+ ]
59
+ end
60
+
61
+ it 'should parse response in UpdateAttributes method' do
62
+ @sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [1] }).should == 1
63
+ result = @sphinx.Query('wifi', 'test1')
64
+ result['matches'][0]['attrs']['group_id'].should == 1
65
+ @sphinx.UpdateAttributes('test1', ['group_id'], { 2 => [2] }).should == 1
66
+ result = @sphinx.Query('wifi', 'test1')
67
+ result['matches'][0]['attrs']['group_id'].should == 2
68
+ end
69
+
70
+ it 'should process errors in Query method' do
71
+ @sphinx.Query('wifi', 'fakeindex').should be_false
72
+ @sphinx.GetLastError.length.should_not == 0
73
+ end
74
+
75
+ it 'should process errors in RunQueries method' do
76
+ @sphinx.AddQuery('wifi', 'fakeindex')
77
+ r = @sphinx.RunQueries
78
+ r.should be_an(Array)
79
+ r[0]['error'].length.should_not == 0
80
+ end
81
+
82
+ def validate_results_wifi(result)
83
+ result['total_found'].should == 3
84
+ result['matches'].length.should == 3
85
+ result['time'].should_not be_nil
86
+ result['attrs'].should == {
87
+ 'group_id' => Sphinx::Client::SPH_ATTR_INTEGER,
88
+ 'created_at' => Sphinx::Client::SPH_ATTR_TIMESTAMP,
89
+ 'rating' => Sphinx::Client::SPH_ATTR_FLOAT,
90
+ 'tags' => Sphinx::Client::SPH_ATTR_MULTI | Sphinx::Client::SPH_ATTR_INTEGER
91
+ }
92
+ result['fields'].should == [ 'name', 'description' ]
93
+ result['total'].should == 3
94
+ result['matches'].should be_an(Array)
95
+
96
+ result['matches'][0]['id'].should == 2
97
+ result['matches'][0]['weight'].should == 2
98
+ result['matches'][0]['attrs']['group_id'].should == 2
99
+ result['matches'][0]['attrs']['created_at'].should == 1175658555
100
+ result['matches'][0]['attrs']['tags'].should == [5, 6, 7, 8]
101
+ ('%0.2f' % result['matches'][0]['attrs']['rating']).should == '54.85'
102
+
103
+ result['matches'][1]['id'].should == 3
104
+ result['matches'][1]['weight'].should == 2
105
+ result['matches'][1]['attrs']['group_id'].should == 1
106
+ result['matches'][1]['attrs']['created_at'].should == 1175658647
107
+ result['matches'][1]['attrs']['tags'].should == [1, 7, 9, 10]
108
+ ('%0.2f' % result['matches'][1]['attrs']['rating']).should == '16.25'
109
+
110
+ result['matches'][2]['id'].should == 1
111
+ result['matches'][2]['weight'].should == 1
112
+ result['matches'][2]['attrs']['group_id'].should == 1
113
+ result['matches'][2]['attrs']['created_at'].should == 1175658490
114
+ result['matches'][2]['attrs']['tags'].should == [1, 2, 3, 4]
115
+ ('%0.2f' % result['matches'][2]['attrs']['rating']).should == '13.32'
116
+
117
+ result['words'].should == { 'wifi' => { 'hits' => 6, 'docs' => 3 } }
118
+ end
119
+ end
120
+
121
+ # To execute these tests you need to execute sphinx_test.sql and configure sphinx using sphinx.conf
122
+ # (both files are placed under sphinx directory)
123
+ describe 'The Sphinx::Client connected to Sphinx' do
124
+ before(:each) { @sphinx = Sphinx::Client.new }
125
+ after (:each) { @sphinx.destroy }
126
+
127
+ it_should_behave_like 'client API library'
128
+ end
129
+
130
+ describe 'The Sphinx::FastClient connected to Sphinx' do
131
+ before(:each) { @sphinx = Sphinx::FastClient.new }
132
+ after (:each) { @sphinx.destroy }
133
+
134
+ it_should_behave_like 'client API library'
135
+ end