rlibsphinxclient 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|