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.
- data/.gitignore +3 -0
- data/CHANGELOG.rdoc +18 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +151 -0
- data/Rakefile +39 -0
- data/VERSION +1 -0
- data/ext/extconf.rb +20 -0
- data/ext/rlibsphinxclient.i +314 -0
- data/ext/rlibsphinxclient_wrap.c +5931 -0
- data/init.rb +1 -0
- data/lib/sphinx.rb +22 -0
- data/lib/sphinx/client.rb +1070 -0
- data/lib/sphinx/fast_client.rb +184 -0
- data/lib/sphinx/request.rb +49 -0
- data/lib/sphinx/response.rb +69 -0
- data/lib/sphinx/safe_executor.rb +11 -0
- data/lib/sphinx/timeout.rb +9 -0
- data/rlibsphinxclient.gemspec +117 -0
- data/spec/client_response_spec.rb +135 -0
- data/spec/client_spec.rb +548 -0
- data/spec/fixtures/default_search.php +8 -0
- data/spec/fixtures/default_search_index.php +8 -0
- data/spec/fixtures/excerpt_custom.php +11 -0
- data/spec/fixtures/excerpt_default.php +8 -0
- data/spec/fixtures/excerpt_flags.php +11 -0
- data/spec/fixtures/field_weights.php +9 -0
- data/spec/fixtures/filter.php +9 -0
- data/spec/fixtures/filter_exclude.php +9 -0
- data/spec/fixtures/filter_float_range.php +9 -0
- data/spec/fixtures/filter_float_range_exclude.php +9 -0
- data/spec/fixtures/filter_range.php +9 -0
- data/spec/fixtures/filter_range_exclude.php +9 -0
- data/spec/fixtures/filter_ranges.php +10 -0
- data/spec/fixtures/filters.php +10 -0
- data/spec/fixtures/filters_different.php +13 -0
- data/spec/fixtures/geo_anchor.php +9 -0
- data/spec/fixtures/group_by_attr.php +9 -0
- data/spec/fixtures/group_by_attrpair.php +9 -0
- data/spec/fixtures/group_by_day.php +9 -0
- data/spec/fixtures/group_by_day_sort.php +9 -0
- data/spec/fixtures/group_by_month.php +9 -0
- data/spec/fixtures/group_by_week.php +9 -0
- data/spec/fixtures/group_by_year.php +9 -0
- data/spec/fixtures/group_distinct.php +10 -0
- data/spec/fixtures/id_range.php +9 -0
- data/spec/fixtures/id_range64.php +9 -0
- data/spec/fixtures/index_weights.php +9 -0
- data/spec/fixtures/keywords.php +8 -0
- data/spec/fixtures/limits.php +9 -0
- data/spec/fixtures/limits_cutoff.php +9 -0
- data/spec/fixtures/limits_max.php +9 -0
- data/spec/fixtures/limits_max_cutoff.php +9 -0
- data/spec/fixtures/match_all.php +9 -0
- data/spec/fixtures/match_any.php +9 -0
- data/spec/fixtures/match_boolean.php +9 -0
- data/spec/fixtures/match_extended.php +9 -0
- data/spec/fixtures/match_extended2.php +9 -0
- data/spec/fixtures/match_fullscan.php +9 -0
- data/spec/fixtures/match_phrase.php +9 -0
- data/spec/fixtures/max_query_time.php +9 -0
- data/spec/fixtures/miltiple_queries.php +12 -0
- data/spec/fixtures/ranking_bm25.php +9 -0
- data/spec/fixtures/ranking_none.php +9 -0
- data/spec/fixtures/ranking_proximity_bm25.php +9 -0
- data/spec/fixtures/ranking_wordcount.php +9 -0
- data/spec/fixtures/retries.php +9 -0
- data/spec/fixtures/retries_delay.php +9 -0
- data/spec/fixtures/sort_attr_asc.php +9 -0
- data/spec/fixtures/sort_attr_desc.php +9 -0
- data/spec/fixtures/sort_expr.php +9 -0
- data/spec/fixtures/sort_extended.php +9 -0
- data/spec/fixtures/sort_relevance.php +9 -0
- data/spec/fixtures/sort_time_segments.php +9 -0
- data/spec/fixtures/sphinxapi.php +1181 -0
- data/spec/fixtures/update_attributes.php +8 -0
- data/spec/fixtures/weights.php +9 -0
- data/spec/sphinx/sphinx.conf +67 -0
- data/spec/sphinx/sphinx_test.sql +86 -0
- 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,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
|