ultrasphinx 1.6 → 1.6.7
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.tar.gz.sig +0 -0
- data/CHANGELOG +5 -1
- data/Manifest +47 -7
- data/README +4 -4
- data/TODO +1 -0
- data/examples/default.base +6 -2
- data/lib/ultrasphinx.rb +1 -1
- data/lib/ultrasphinx/configure.rb +53 -28
- data/lib/ultrasphinx/fields.rb +16 -13
- data/lib/ultrasphinx/postgresql/concat_ws.sql +35 -0
- data/lib/ultrasphinx/postgresql/crc32.sql +7 -0
- data/lib/ultrasphinx/postgresql/group_concat.sql +25 -0
- data/lib/ultrasphinx/{hex_to_int.sql → postgresql/hex_to_int.sql} +0 -0
- data/lib/ultrasphinx/postgresql/language.sql +1 -0
- data/lib/ultrasphinx/postgresql/unix_timestamp.sql +12 -0
- data/lib/ultrasphinx/search/internals.rb +42 -16
- data/lib/ultrasphinx/ultrasphinx.rb +23 -12
- data/test/integration/app/app/models/person/user.rb +1 -1
- data/test/integration/app/config/database.yml +9 -13
- data/test/integration/app/config/ultrasphinx/development.conf +6 -6
- data/test/integration/app/config/ultrasphinx/development.conf.canonical +6 -6
- data/test/integration/app/db/schema.rb +9 -2
- data/test/integration/search_test.rb +16 -6
- data/test/setup.rb +5 -1
- data/test/ts.multi +2 -0
- data/ultrasphinx.gemspec +5 -5
- data/vendor/riddle/{MIT-LICENSE → MIT-LICENCE} +0 -0
- data/vendor/riddle/README +60 -0
- data/vendor/riddle/Rakefile +25 -0
- data/vendor/riddle/{riddle.rb → lib/riddle.rb} +3 -0
- data/vendor/riddle/{riddle → lib/riddle}/client.rb +73 -4
- data/vendor/riddle/{riddle → lib/riddle}/client/filter.rb +0 -0
- data/vendor/riddle/{riddle → lib/riddle}/client/message.rb +2 -0
- data/vendor/riddle/{riddle → lib/riddle}/client/response.rb +0 -0
- data/vendor/riddle/spec/fixtures/data/anchor.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/any.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/boolean.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/distinct.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter_array.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter_array_exclude.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter_floats.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter_floats_exclude.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter_floats_range.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter_range.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter_range_exclude.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/group.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/index.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/phrase.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/simple.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/sort.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/update_simple.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/weights.bin +0 -0
- data/vendor/riddle/spec/fixtures/sphinx/configuration.erb +38 -0
- data/vendor/riddle/spec/fixtures/sql/conf.example.yml +3 -0
- data/vendor/riddle/spec/fixtures/sql/data.sql +25000 -0
- data/vendor/riddle/spec/fixtures/sql/structure.sql +16 -0
- data/vendor/riddle/spec/functional/excerpt_spec.rb +102 -0
- data/vendor/riddle/spec/functional/search_spec.rb +69 -0
- data/vendor/riddle/spec/functional/update_spec.rb +41 -0
- data/vendor/riddle/spec/spec_helper.rb +25 -0
- data/vendor/riddle/spec/sphinx_helper.rb +91 -0
- data/vendor/riddle/spec/unit/client_spec.rb +140 -0
- data/vendor/riddle/spec/unit/filter_spec.rb +33 -0
- data/vendor/riddle/spec/unit/message_spec.rb +63 -0
- data/vendor/riddle/spec/unit/response_spec.rb +64 -0
- metadata +95 -55
- metadata.gz.sig +0 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
mysqlcompat-1.0b3
|
4
|
+
public domain
|
5
|
+
GROUP_CONCAT()
|
6
|
+
Note: For DISTINCT and ORDER BY a subquery is required
|
7
|
+
*/
|
8
|
+
|
9
|
+
CREATE OR REPLACE FUNCTION _group_concat(text, text)
|
10
|
+
RETURNS text AS $$
|
11
|
+
SELECT CASE
|
12
|
+
WHEN $2 IS NULL THEN $1
|
13
|
+
WHEN $1 IS NULL THEN $2
|
14
|
+
ELSE $1 operator(pg_catalog.||) ' ' operator(pg_catalog.||) $2
|
15
|
+
END
|
16
|
+
$$ IMMUTABLE LANGUAGE SQL;
|
17
|
+
|
18
|
+
DROP AGGREGATE IF EXISTS group_concat(text);
|
19
|
+
|
20
|
+
CREATE AGGREGATE group_concat (
|
21
|
+
BASETYPE = text,
|
22
|
+
SFUNC = _group_concat,
|
23
|
+
STYPE = text
|
24
|
+
);
|
25
|
+
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
CREATE LANGUAGE 'plpgsql';
|
@@ -157,28 +157,53 @@ module Ultrasphinx
|
|
157
157
|
|
158
158
|
def rebuild_facet_cache(facet)
|
159
159
|
# Cache the reverse hash map for the textual facet if it hasn't been done yet
|
160
|
-
# XXX
|
160
|
+
# XXX Not necessarily optimal since it requires a direct DB hit once per mongrel
|
161
161
|
Ultrasphinx.say "caching hash reverse map for text facet #{facet}"
|
162
162
|
|
163
|
-
Fields.instance.classes[facet].
|
164
|
-
|
165
|
-
|
166
|
-
|
163
|
+
configured_classes = Fields.instance.classes[facet].map do |klass|
|
164
|
+
|
165
|
+
# Concatenates might not work well
|
166
|
+
type, configuration = nil, nil
|
167
|
+
MODEL_CONFIGURATION[klass.name].except('conditions').each do |_type, values|
|
168
|
+
type = _type
|
169
|
+
configuration = values.detect { |this_field| this_field['as'] == facet }
|
170
|
+
break if configuration
|
167
171
|
end
|
168
172
|
|
169
|
-
|
170
|
-
|
173
|
+
unless configuration and configuration['facet']
|
174
|
+
Ultrasphinx.say "model #{klass.name} has the requested '#{facet}' field, but it was not configured for faceting, and will be skipped"
|
175
|
+
next
|
176
|
+
end
|
177
|
+
|
178
|
+
FACET_CACHE[facet] ||= {}
|
171
179
|
|
172
|
-
|
173
|
-
|
180
|
+
# XXX This is a duplication of stuff already known in configure.rb, and ought to be cleaned up,
|
181
|
+
# but that would mean we have to either parse the .conf or configure every time at boot
|
182
|
+
|
183
|
+
field_string, join_string = case type
|
184
|
+
when 'fields'
|
185
|
+
[configuration['field'], ""]
|
186
|
+
when 'include'
|
187
|
+
# XXX Only handles the basic case. No test coverage.
|
188
|
+
["included.#{configuration['field']}",
|
189
|
+
(configuration['association_sql'] or "LEFT OUTER JOIN #{configuration['table']} AS included ON included.#{configuration['class_name'].constantize.primary_key} = #{klass.table_name}.#{configuration['class_name'].underscore}_id")
|
190
|
+
]
|
191
|
+
when 'concatenate'
|
192
|
+
# Wait for someone to complain before worrying about this
|
193
|
+
raise "Concatenation text facets have not been implemented"
|
174
194
|
end
|
175
|
-
|
176
|
-
klass.connection.execute("SELECT #{
|
177
|
-
|
195
|
+
|
196
|
+
klass.connection.execute("SELECT #{field_string} AS value, CRC32(#{field_string}) AS hash FROM #{klass.table_name} #{join_string} GROUP BY value").each do |value, hash|
|
197
|
+
FACET_CACHE[facet][hash.to_i] = value
|
178
198
|
end
|
199
|
+
klass
|
179
200
|
end
|
201
|
+
|
202
|
+
configured_classes.compact!
|
203
|
+
raise ConfigurationError, "no classes were correctly configured for text faceting on '#{facet}'" if configured_classes.empty?
|
204
|
+
|
180
205
|
FACET_CACHE[facet]
|
181
|
-
end
|
206
|
+
end
|
182
207
|
|
183
208
|
# Inverse-modulus map the Sphinx ids to the table-specific ids
|
184
209
|
def convert_sphinx_ids(sphinx_ids)
|
@@ -204,12 +229,13 @@ module Ultrasphinx
|
|
204
229
|
end
|
205
230
|
|
206
231
|
# Load it
|
207
|
-
|
232
|
+
begin
|
208
233
|
# XXX Does not use Memcached's multiget, or MySQL's, for that matter
|
209
|
-
klass.send(finder, id)
|
234
|
+
record = klass.send(finder, id)
|
235
|
+
raise ActiveRecord::RecordNotFound unless record
|
210
236
|
rescue ActiveRecord::RecordNotFound => e
|
211
237
|
if Ultrasphinx::Search.client_options['ignore_missing_records']
|
212
|
-
|
238
|
+
say "warning; #{klass}.#{finder}(#{id}) returned RecordNotFound"
|
213
239
|
else
|
214
240
|
raise(e)
|
215
241
|
end
|
@@ -49,18 +49,26 @@ module Ultrasphinx
|
|
49
49
|
CONNECTION_DEFAULTS = {
|
50
50
|
:host => 'localhost'
|
51
51
|
}
|
52
|
+
|
53
|
+
mattr_accessor :with_rake
|
54
|
+
|
55
|
+
def self.load_stored_procedure(name)
|
56
|
+
open("#{THIS_DIR}/postgresql/#{name}.sql").read.gsub(/\s+/, ' ')
|
57
|
+
end
|
52
58
|
|
53
59
|
ADAPTER_SQL_FUNCTIONS = {
|
54
60
|
'mysql' => {
|
55
|
-
'
|
56
|
-
'
|
57
|
-
|
58
|
-
},
|
61
|
+
'group_concat' => "CAST(GROUP_CONCAT(DISTINCT ? SEPARATOR ' ') AS CHAR)",
|
62
|
+
'stored_procedures' => {}
|
63
|
+
},
|
59
64
|
'postgresql' => {
|
60
|
-
'
|
61
|
-
'
|
62
|
-
|
63
|
-
|
65
|
+
'group_concat' => "GROUP_CONCAT(?)",
|
66
|
+
'stored_procedures' => Hash[*(
|
67
|
+
['hex_to_int', 'group_concat', 'concat_ws', 'unix_timestamp', 'crc32'].map do |name|
|
68
|
+
[name, load_stored_procedure(name)]
|
69
|
+
end.flatten
|
70
|
+
)
|
71
|
+
]
|
64
72
|
}
|
65
73
|
}
|
66
74
|
|
@@ -72,14 +80,17 @@ sql_query_pre = SET NAMES utf8
|
|
72
80
|
),
|
73
81
|
'postgresql' => %(
|
74
82
|
type = pgsql
|
75
|
-
sql_query_pre = ) + ADAPTER_SQL_FUNCTIONS['postgresql']['
|
83
|
+
sql_query_pre = ) + ADAPTER_SQL_FUNCTIONS['postgresql']['stored_procedures'].values.join(' ') + %(
|
76
84
|
)
|
77
85
|
}
|
78
86
|
|
79
87
|
ADAPTER = ActiveRecord::Base.connection.instance_variable_get("@config")[:adapter] rescue 'mysql'
|
80
|
-
|
81
|
-
|
82
|
-
|
88
|
+
|
89
|
+
# Install the stored procedures
|
90
|
+
ADAPTER_SQL_FUNCTIONS[ADAPTER]['stored_procedures'].each do |key, value|
|
91
|
+
ActiveRecord::Base.connection.execute(value)
|
92
|
+
end
|
93
|
+
|
83
94
|
# Logger.
|
84
95
|
def self.say msg
|
85
96
|
if with_rake
|
@@ -5,6 +5,6 @@ class User < ActiveRecord::Base
|
|
5
5
|
is_indexed :fields => ['login', 'email', 'deleted'],
|
6
6
|
:include => [{:class_name => 'Seller', :field => 'company_name', :as => 'company'},
|
7
7
|
{:class_name => 'Seller', :field => 'sellers_two.company_name', :as => 'company_two', 'association_sql' => 'LEFT OUTER JOIN sellers AS sellers_two ON users.id = sellers_two.user_id', 'function_sql' => "REPLACE(?, '6', ' replacement ')"}],
|
8
|
-
:conditions =>
|
8
|
+
:conditions => "deleted = '0'"
|
9
9
|
|
10
10
|
end
|
@@ -1,21 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
adapter: mysql
|
1
|
+
defaults: &defaults
|
2
|
+
adapter: <%= ENV['DB'] || 'mysql' %>
|
4
3
|
host: localhost
|
5
|
-
database: ultrasphinx_development
|
6
4
|
username: root
|
7
5
|
password:
|
6
|
+
|
7
|
+
development:
|
8
|
+
<<: *defaults
|
9
|
+
database: ultrasphinx_development
|
8
10
|
|
9
11
|
test:
|
10
|
-
|
11
|
-
host: localhost
|
12
|
+
<<: *defaults
|
12
13
|
database: ultrasphinx_test
|
13
|
-
|
14
|
-
password:
|
15
|
-
|
14
|
+
|
16
15
|
production:
|
17
|
-
|
18
|
-
host: localhost
|
16
|
+
<<: *defaults
|
19
17
|
database: ultrasphinx_production
|
20
|
-
username: root
|
21
|
-
password:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
|
-
# Auto-generated at Wed
|
2
|
+
# Auto-generated at Wed Dec 12 12:09:45 -0500 2007.
|
3
3
|
# Hand modifications will be overwritten.
|
4
|
-
# /Users/eweaver/Desktop/projects/
|
4
|
+
# /Users/eweaver/Desktop/projects/chow/vendor/plugins/ultrasphinx/test/integration/app/config/ultrasphinx/default.base
|
5
5
|
indexer {
|
6
6
|
mem_limit = 256M
|
7
7
|
}
|
@@ -34,7 +34,7 @@ sql_host = localhost
|
|
34
34
|
sql_pass =
|
35
35
|
sql_user = root
|
36
36
|
sql_query_range = SELECT MIN(id), MAX(id) FROM states
|
37
|
-
sql_query = SELECT (states.id * 4 + 0) AS id, CAST(GROUP_CONCAT(DISTINCT addresses.name SEPARATOR ' ') AS CHAR) AS address_name, 0 AS capitalization, 'Geo::State' AS class, 0 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, '' AS content,
|
37
|
+
sql_query = SELECT (states.id * 4 + 0) AS id, CAST(GROUP_CONCAT(DISTINCT addresses.name SEPARATOR ' ') AS CHAR) AS address_name, 0 AS capitalization, 'Geo::State' AS class, 0 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, '' AS content, 18000 AS created_at, 0 AS deleted, '' AS email, '' AS login, '' AS mission_statement, '' AS name, '' AS state, 0 AS user_id FROM states LEFT OUTER JOIN addresses AS addresses ON states.id = addresses.state_id WHERE states.id >= $start AND states.id <= $end GROUP BY states.id
|
38
38
|
|
39
39
|
sql_group_column = capitalization
|
40
40
|
sql_group_column = class_id
|
@@ -65,7 +65,7 @@ sql_host = localhost
|
|
65
65
|
sql_pass =
|
66
66
|
sql_user = root
|
67
67
|
sql_query_range = SELECT MIN(id), MAX(id) FROM sellers
|
68
|
-
sql_query = SELECT (sellers.id * 4 + 1) AS id, '' AS address_name, sellers.capitalization AS capitalization, 'Seller' AS class, 1 AS class_id, '' AS company, sellers.company_name AS company_name, CRC32(sellers.company_name) AS company_name_facet, '' AS company_two, '' AS content, UNIX_TIMESTAMP(sellers.created_at) AS created_at, 0 AS deleted, '' AS email, '' AS login, sellers.mission_statement AS mission_statement, '' AS name, '' AS state, sellers.user_id AS user_id FROM sellers WHERE sellers.id >= $start AND sellers.id <= $end GROUP BY id
|
68
|
+
sql_query = SELECT (sellers.id * 4 + 1) AS id, '' AS address_name, sellers.capitalization AS capitalization, 'Seller' AS class, 1 AS class_id, '' AS company, sellers.company_name AS company_name, CRC32(sellers.company_name) AS company_name_facet, '' AS company_two, '' AS content, UNIX_TIMESTAMP(sellers.created_at) AS created_at, 0 AS deleted, '' AS email, '' AS login, sellers.mission_statement AS mission_statement, '' AS name, '' AS state, sellers.user_id AS user_id FROM sellers WHERE sellers.id >= $start AND sellers.id <= $end GROUP BY sellers.id
|
69
69
|
|
70
70
|
sql_group_column = capitalization
|
71
71
|
sql_group_column = class_id
|
@@ -96,7 +96,7 @@ sql_host = localhost
|
|
96
96
|
sql_pass =
|
97
97
|
sql_user = root
|
98
98
|
sql_query_range = SELECT MIN(id), MAX(id) FROM addresses
|
99
|
-
sql_query = SELECT (addresses.id * 4 + 2) AS id, '' AS address_name, 0 AS capitalization, 'Geo::Address' AS class, 2 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, CONCAT_WS(' ', addresses.line_1, addresses.line_2, addresses.city, addresses.province_region, addresses.zip_postal_code) AS content,
|
99
|
+
sql_query = SELECT (addresses.id * 4 + 2) AS id, '' AS address_name, 0 AS capitalization, 'Geo::Address' AS class, 2 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, CONCAT_WS(' ', addresses.line_1, addresses.line_2, addresses.city, addresses.province_region, addresses.zip_postal_code) AS content, 18000 AS created_at, 0 AS deleted, '' AS email, '' AS login, '' AS mission_statement, addresses.name AS name, states.name AS state, 0 AS user_id FROM addresses LEFT OUTER JOIN states AS states ON states.id = addresses.state_id WHERE addresses.id >= $start AND addresses.id <= $end GROUP BY addresses.id
|
100
100
|
|
101
101
|
sql_group_column = capitalization
|
102
102
|
sql_group_column = class_id
|
@@ -127,7 +127,7 @@ sql_host = localhost
|
|
127
127
|
sql_pass =
|
128
128
|
sql_user = root
|
129
129
|
sql_query_range = SELECT MIN(id), MAX(id) FROM users
|
130
|
-
sql_query = SELECT (users.id * 4 + 3) AS id, '' AS address_name, 0 AS capitalization, 'User' AS class, 3 AS class_id, sellers.company_name AS company, '' AS company_name, 0 AS company_name_facet, REPLACE(sellers_two.company_name, '6', ' replacement ') AS company_two, '' AS content,
|
130
|
+
sql_query = SELECT (users.id * 4 + 3) AS id, '' AS address_name, 0 AS capitalization, 'User' AS class, 3 AS class_id, sellers.company_name AS company, '' AS company_name, 0 AS company_name_facet, REPLACE(sellers_two.company_name, '6', ' replacement ') AS company_two, '' AS content, 18000 AS created_at, users.deleted AS deleted, users.email AS email, users.login AS login, '' AS mission_statement, '' AS name, '' AS state, 0 AS user_id FROM users LEFT OUTER JOIN sellers AS sellers ON users.id = sellers.user_id LEFT OUTER JOIN sellers AS sellers_two ON users.id = sellers_two.user_id WHERE users.id >= $start AND users.id <= $end AND (deleted = '0') GROUP BY users.id
|
131
131
|
|
132
132
|
sql_group_column = capitalization
|
133
133
|
sql_group_column = class_id
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
|
-
# Auto-generated at Wed
|
2
|
+
# Auto-generated at Wed Dec 12 02:47:44 -0500 2007.
|
3
3
|
# Hand modifications will be overwritten.
|
4
|
-
# /Users/eweaver/Desktop/projects/
|
4
|
+
# /Users/eweaver/Desktop/projects/chow/vendor/plugins/ultrasphinx/test/integration/app/config/ultrasphinx/default.base
|
5
5
|
indexer {
|
6
6
|
mem_limit = 256M
|
7
7
|
}
|
@@ -34,7 +34,7 @@ sql_host = localhost
|
|
34
34
|
sql_pass =
|
35
35
|
sql_user = root
|
36
36
|
sql_query_range = SELECT MIN(id), MAX(id) FROM states
|
37
|
-
sql_query = SELECT (states.id * 4 + 0) AS id, CAST(GROUP_CONCAT(DISTINCT addresses.name SEPARATOR ' ') AS CHAR) AS address_name, 0 AS capitalization, 'Geo::State' AS class, 0 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, '' AS content,
|
37
|
+
sql_query = SELECT (states.id * 4 + 0) AS id, CAST(GROUP_CONCAT(DISTINCT addresses.name SEPARATOR ' ') AS CHAR) AS address_name, 0 AS capitalization, 'Geo::State' AS class, 0 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, '' AS content, 18000 AS created_at, 0 AS deleted, '' AS email, '' AS login, '' AS mission_statement, '' AS name, '' AS state, 0 AS user_id FROM states LEFT OUTER JOIN addresses AS addresses ON states.id = addresses.state_id WHERE states.id >= $start AND states.id <= $end GROUP BY states.id
|
38
38
|
|
39
39
|
sql_group_column = capitalization
|
40
40
|
sql_group_column = class_id
|
@@ -65,7 +65,7 @@ sql_host = localhost
|
|
65
65
|
sql_pass =
|
66
66
|
sql_user = root
|
67
67
|
sql_query_range = SELECT MIN(id), MAX(id) FROM sellers
|
68
|
-
sql_query = SELECT (sellers.id * 4 + 1) AS id, '' AS address_name, sellers.capitalization AS capitalization, 'Seller' AS class, 1 AS class_id, '' AS company, sellers.company_name AS company_name, CRC32(sellers.company_name) AS company_name_facet, '' AS company_two, '' AS content, UNIX_TIMESTAMP(sellers.created_at) AS created_at, 0 AS deleted, '' AS email, '' AS login, sellers.mission_statement AS mission_statement, '' AS name, '' AS state, sellers.user_id AS user_id FROM sellers WHERE sellers.id >= $start AND sellers.id <= $end GROUP BY id
|
68
|
+
sql_query = SELECT (sellers.id * 4 + 1) AS id, '' AS address_name, sellers.capitalization AS capitalization, 'Seller' AS class, 1 AS class_id, '' AS company, sellers.company_name AS company_name, CRC32(sellers.company_name) AS company_name_facet, '' AS company_two, '' AS content, UNIX_TIMESTAMP(sellers.created_at) AS created_at, 0 AS deleted, '' AS email, '' AS login, sellers.mission_statement AS mission_statement, '' AS name, '' AS state, sellers.user_id AS user_id FROM sellers WHERE sellers.id >= $start AND sellers.id <= $end GROUP BY sellers.id
|
69
69
|
|
70
70
|
sql_group_column = capitalization
|
71
71
|
sql_group_column = class_id
|
@@ -96,7 +96,7 @@ sql_host = localhost
|
|
96
96
|
sql_pass =
|
97
97
|
sql_user = root
|
98
98
|
sql_query_range = SELECT MIN(id), MAX(id) FROM addresses
|
99
|
-
sql_query = SELECT (addresses.id * 4 + 2) AS id, '' AS address_name, 0 AS capitalization, 'Geo::Address' AS class, 2 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, CONCAT_WS(' ', addresses.line_1, addresses.line_2, addresses.city, addresses.province_region, addresses.zip_postal_code) AS content,
|
99
|
+
sql_query = SELECT (addresses.id * 4 + 2) AS id, '' AS address_name, 0 AS capitalization, 'Geo::Address' AS class, 2 AS class_id, '' AS company, '' AS company_name, 0 AS company_name_facet, '' AS company_two, CONCAT_WS(' ', addresses.line_1, addresses.line_2, addresses.city, addresses.province_region, addresses.zip_postal_code) AS content, 18000 AS created_at, 0 AS deleted, '' AS email, '' AS login, '' AS mission_statement, addresses.name AS name, states.name AS state, 0 AS user_id FROM addresses LEFT OUTER JOIN states AS states ON states.id = addresses.state_id WHERE addresses.id >= $start AND addresses.id <= $end GROUP BY addresses.id
|
100
100
|
|
101
101
|
sql_group_column = capitalization
|
102
102
|
sql_group_column = class_id
|
@@ -127,7 +127,7 @@ sql_host = localhost
|
|
127
127
|
sql_pass =
|
128
128
|
sql_user = root
|
129
129
|
sql_query_range = SELECT MIN(id), MAX(id) FROM users
|
130
|
-
sql_query = SELECT (users.id * 4 + 3) AS id, '' AS address_name, 0 AS capitalization, 'User' AS class, 3 AS class_id, sellers.company_name AS company, '' AS company_name, 0 AS company_name_facet, REPLACE(sellers_two.company_name, '6', ' replacement ') AS company_two, '' AS content,
|
130
|
+
sql_query = SELECT (users.id * 4 + 3) AS id, '' AS address_name, 0 AS capitalization, 'User' AS class, 3 AS class_id, sellers.company_name AS company, '' AS company_name, 0 AS company_name_facet, REPLACE(sellers_two.company_name, '6', ' replacement ') AS company_two, '' AS content, 18000 AS created_at, users.deleted AS deleted, users.email AS email, users.login AS login, '' AS mission_statement, '' AS name, '' AS state, 0 AS user_id FROM users LEFT OUTER JOIN sellers AS sellers ON users.id = sellers.user_id LEFT OUTER JOIN sellers AS sellers_two ON users.id = sellers_two.user_id WHERE users.id >= $start AND users.id <= $end AND (deleted = '0') GROUP BY users.id
|
131
131
|
|
132
132
|
sql_group_column = capitalization
|
133
133
|
sql_group_column = class_id
|
@@ -1,6 +1,13 @@
|
|
1
|
-
# This file is
|
2
|
-
# migrations feature of ActiveRecord to incrementally modify your database, and
|
1
|
+
# This file is auto-generated from the current state of the database. Instead of editing this file,
|
2
|
+
# please use the migrations feature of ActiveRecord to incrementally modify your database, and
|
3
3
|
# then regenerate this schema definition.
|
4
|
+
#
|
5
|
+
# Note that this schema.rb definition is the authoritative source for your database schema. If you need
|
6
|
+
# to create the application database on another system, you should be using db:schema:load, not running
|
7
|
+
# all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
8
|
+
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
9
|
+
#
|
10
|
+
# It's strongly recommended to check this file into your version control system.
|
4
11
|
|
5
12
|
ActiveRecord::Schema.define(:version => 8) do
|
6
13
|
|
@@ -68,18 +68,20 @@ class SearchTest < Test::Unit::TestCase
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def test_empty_query
|
71
|
+
assert_nothing_raised do
|
72
|
+
@s = S.new.run
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_total_entries
|
71
77
|
@total = Ultrasphinx::MODEL_CONFIGURATION.keys.inject(0) do |acc, class_name|
|
72
78
|
acc + class_name.constantize.count
|
73
79
|
end - User.count(:conditions => {:deleted => true })
|
74
80
|
|
75
|
-
assert_nothing_raised do
|
76
|
-
@s = S.new.run
|
77
|
-
end
|
78
|
-
|
79
81
|
assert_equal(
|
80
82
|
@total,
|
81
|
-
@s.total_entries
|
82
|
-
)
|
83
|
+
@s = S.new.run.total_entries
|
84
|
+
)
|
83
85
|
end
|
84
86
|
|
85
87
|
def test_sort_by_date
|
@@ -101,8 +103,16 @@ class SearchTest < Test::Unit::TestCase
|
|
101
103
|
Seller.find(:all, :limit => 5, :order => 'mission_statement ASC').map(&:mission_statement),
|
102
104
|
S.new(:class_names => 'Seller', :sort_by => 'mission_statement', :sort_mode => 'ascending', :per_page => 5).run.map(&:mission_statement)
|
103
105
|
)
|
106
|
+
assert S.new(:sort_by => 'mission_statement', :sort_mode => 'ascending').run.size > 0
|
104
107
|
end
|
105
108
|
|
109
|
+
def test_sort_by_string_using_query
|
110
|
+
assert_equal(
|
111
|
+
Seller.find(10,11, :order => 'mission_statement ASC').map(&:mission_statement),
|
112
|
+
S.new(:class_names => 'Seller', :query => 'seller10 or seller11', :sort_by => 'mission_statement', :sort_mode => 'ascending', :per_page => 2).run.map(&:mission_statement)
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
106
116
|
def test_filter
|
107
117
|
assert_equal(
|
108
118
|
Seller.count(:conditions => 'user_id = 17'),
|
data/test/setup.rb
CHANGED
@@ -5,11 +5,15 @@ puts ["Please make sure that test/integration/app/vendor/rails is symlinked",
|
|
5
5
|
"to a Rails trunk checkout in order for the rake tasks to run properly."]
|
6
6
|
|
7
7
|
Dir.chdir "#{File.dirname(__FILE__)}/integration/app/" do
|
8
|
+
system("killall searchd")
|
9
|
+
system("rm -rf /tmp/sphinx")
|
10
|
+
system("rm -rf config/ultrasphinx/development.conf")
|
8
11
|
Dir.chdir "vendor/plugins" do
|
9
12
|
system("rm ultrasphinx; ln -s ../../../../../ ultrasphinx")
|
10
13
|
end
|
11
14
|
system("rake db:create")
|
12
15
|
system("rake db:migrate db:fixtures:load")
|
13
16
|
system("rake us:boot")
|
14
|
-
system("
|
17
|
+
system("rm /tmp/ultrasphinx-stopwords.txt")
|
18
|
+
system("rake ultrasphinx:spelling:build")
|
15
19
|
end
|
data/test/ts.multi
ADDED
data/ultrasphinx.gemspec
CHANGED
@@ -1,24 +1,24 @@
|
|
1
1
|
|
2
|
-
# Gem::Specification for Ultrasphinx-1.6
|
2
|
+
# Gem::Specification for Ultrasphinx-1.6.7
|
3
3
|
# Originally generated by Echoe
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
6
|
s.name = %q{ultrasphinx}
|
7
|
-
s.version = "1.6"
|
7
|
+
s.version = "1.6.7"
|
8
8
|
|
9
9
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.authors = [""]
|
13
|
-
s.date = %q{2007-
|
13
|
+
s.date = %q{2007-12-13}
|
14
14
|
s.description = %q{Ruby on Rails configurator and client to the Sphinx fulltext search engine.}
|
15
15
|
s.email = %q{}
|
16
|
-
s.files = ["CHANGELOG", "examples/ap.multi", "examples/default.base", "init.rb", "lib/ultrasphinx/autoload.rb", "lib/ultrasphinx/configure.rb", "lib/ultrasphinx/core_extensions.rb", "lib/ultrasphinx/fields.rb", "lib/ultrasphinx/hex_to_int.sql", "lib/ultrasphinx/
|
16
|
+
s.files = ["CHANGELOG", "examples/ap.multi", "examples/default.base", "init.rb", "lib/ultrasphinx/autoload.rb", "lib/ultrasphinx/configure.rb", "lib/ultrasphinx/core_extensions.rb", "lib/ultrasphinx/fields.rb", "lib/ultrasphinx/is_indexed.rb", "lib/ultrasphinx/postgresql/concat_ws.sql", "lib/ultrasphinx/postgresql/crc32.sql", "lib/ultrasphinx/postgresql/group_concat.sql", "lib/ultrasphinx/postgresql/hex_to_int.sql", "lib/ultrasphinx/postgresql/language.sql", "lib/ultrasphinx/postgresql/unix_timestamp.sql", "lib/ultrasphinx/search/internals.rb", "lib/ultrasphinx/search/parser.rb", "lib/ultrasphinx/search.rb", "lib/ultrasphinx/spell.rb", "lib/ultrasphinx/ultrasphinx.rb", "lib/ultrasphinx.rb", "LICENSE", "Manifest", "README", "tasks/ultrasphinx.rake", "test/config/ultrasphinx/test.base", "test/integration/app/app/controllers/addresses_controller.rb", "test/integration/app/app/controllers/application.rb", "test/integration/app/app/controllers/sellers_controller.rb", "test/integration/app/app/controllers/states_controller.rb", "test/integration/app/app/controllers/users_controller.rb", "test/integration/app/app/helpers/addresses_helper.rb", "test/integration/app/app/helpers/application_helper.rb", "test/integration/app/app/helpers/sellers_helper.rb", "test/integration/app/app/helpers/states_helper.rb", "test/integration/app/app/helpers/users_helper.rb", "test/integration/app/app/models/geo/address.rb", "test/integration/app/app/models/geo/state.rb", "test/integration/app/app/models/person/user.rb", "test/integration/app/app/models/seller.rb", "test/integration/app/app/views/addresses/edit.html.erb", "test/integration/app/app/views/addresses/index.html.erb", "test/integration/app/app/views/addresses/new.html.erb", "test/integration/app/app/views/addresses/show.html.erb", "test/integration/app/app/views/layouts/addresses.html.erb", "test/integration/app/app/views/layouts/sellers.html.erb", "test/integration/app/app/views/layouts/states.html.erb", "test/integration/app/app/views/layouts/users.html.erb", "test/integration/app/app/views/sellers/edit.html.erb", "test/integration/app/app/views/sellers/index.html.erb", "test/integration/app/app/views/sellers/new.html.erb", "test/integration/app/app/views/sellers/show.html.erb", "test/integration/app/app/views/states/edit.html.erb", "test/integration/app/app/views/states/index.html.erb", "test/integration/app/app/views/states/new.html.erb", "test/integration/app/app/views/states/show.html.erb", "test/integration/app/app/views/users/edit.html.erb", "test/integration/app/app/views/users/index.html.erb", "test/integration/app/app/views/users/new.html.erb", "test/integration/app/app/views/users/show.html.erb", "test/integration/app/config/boot.rb", "test/integration/app/config/database.yml", "test/integration/app/config/environment.rb", "test/integration/app/config/environments/development.rb", "test/integration/app/config/environments/production.rb", "test/integration/app/config/environments/test.rb", "test/integration/app/config/locomotive.yml", "test/integration/app/config/routes.rb", "test/integration/app/config/ultrasphinx/default.base", "test/integration/app/config/ultrasphinx/development.conf", "test/integration/app/config/ultrasphinx/development.conf.canonical", "test/integration/app/db/migrate/001_create_users.rb", "test/integration/app/db/migrate/002_create_sellers.rb", "test/integration/app/db/migrate/003_create_addresses.rb", "test/integration/app/db/migrate/004_create_states.rb", "test/integration/app/db/migrate/005_add_capitalization_to_seller.rb", "test/integration/app/db/migrate/006_add_deleted_to_user.rb", "test/integration/app/db/migrate/007_add_lat_and_long_to_address.rb", "test/integration/app/db/migrate/008_add_mission_statement_to_seller.rb", "test/integration/app/db/schema.rb", "test/integration/app/doc/README_FOR_APP", "test/integration/app/public/404.html", "test/integration/app/public/500.html", "test/integration/app/public/dispatch.cgi", "test/integration/app/public/dispatch.fcgi", "test/integration/app/public/dispatch.rb", "test/integration/app/public/favicon.ico", "test/integration/app/public/images/rails.png", "test/integration/app/public/index.html", "test/integration/app/public/javascripts/application.js", "test/integration/app/public/javascripts/controls.js", "test/integration/app/public/javascripts/dragdrop.js", "test/integration/app/public/javascripts/effects.js", "test/integration/app/public/javascripts/prototype.js", "test/integration/app/public/robots.txt", "test/integration/app/public/stylesheets/scaffold.css", "test/integration/app/Rakefile", "test/integration/app/README", "test/integration/app/script/about", "test/integration/app/script/breakpointer", "test/integration/app/script/console", "test/integration/app/script/destroy", "test/integration/app/script/generate", "test/integration/app/script/performance/benchmarker", "test/integration/app/script/performance/profiler", "test/integration/app/script/plugin", "test/integration/app/script/process/inspector", "test/integration/app/script/process/reaper", "test/integration/app/script/process/spawner", "test/integration/app/script/runner", "test/integration/app/script/server", "test/integration/app/test/fixtures/addresses.yml", "test/integration/app/test/fixtures/sellers.yml", "test/integration/app/test/fixtures/states.yml", "test/integration/app/test/fixtures/users.yml", "test/integration/app/test/functional/addresses_controller_test.rb", "test/integration/app/test/functional/sellers_controller_test.rb", "test/integration/app/test/functional/states_controller_test.rb", "test/integration/app/test/functional/users_controller_test.rb", "test/integration/app/test/test_helper.rb", "test/integration/app/test/unit/address_test.rb", "test/integration/app/test/unit/seller_test.rb", "test/integration/app/test/unit/state_test.rb", "test/integration/app/test/unit/user_test.rb", "test/integration/configure_test.rb", "test/integration/search_test.rb", "test/integration/server_test.rb", "test/integration/spell_test.rb", "test/setup.rb", "test/test_all.rb", "test/test_helper.rb", "test/ts.multi", "test/unit/parser_test.rb", "TODO", "vendor/riddle/lib/riddle/client/filter.rb", "vendor/riddle/lib/riddle/client/message.rb", "vendor/riddle/lib/riddle/client/response.rb", "vendor/riddle/lib/riddle/client.rb", "vendor/riddle/lib/riddle.rb", "vendor/riddle/MIT-LICENCE", "vendor/riddle/Rakefile", "vendor/riddle/README", "vendor/riddle/spec/fixtures/data/anchor.bin", "vendor/riddle/spec/fixtures/data/any.bin", "vendor/riddle/spec/fixtures/data/boolean.bin", "vendor/riddle/spec/fixtures/data/distinct.bin", "vendor/riddle/spec/fixtures/data/filter.bin", "vendor/riddle/spec/fixtures/data/filter_array.bin", "vendor/riddle/spec/fixtures/data/filter_array_exclude.bin", "vendor/riddle/spec/fixtures/data/filter_floats.bin", "vendor/riddle/spec/fixtures/data/filter_floats_exclude.bin", "vendor/riddle/spec/fixtures/data/filter_floats_range.bin", "vendor/riddle/spec/fixtures/data/filter_range.bin", "vendor/riddle/spec/fixtures/data/filter_range_exclude.bin", "vendor/riddle/spec/fixtures/data/group.bin", "vendor/riddle/spec/fixtures/data/index.bin", "vendor/riddle/spec/fixtures/data/phrase.bin", "vendor/riddle/spec/fixtures/data/simple.bin", "vendor/riddle/spec/fixtures/data/sort.bin", "vendor/riddle/spec/fixtures/data/update_simple.bin", "vendor/riddle/spec/fixtures/data/weights.bin", "vendor/riddle/spec/fixtures/sphinx/configuration.erb", "vendor/riddle/spec/fixtures/sql/conf.example.yml", "vendor/riddle/spec/fixtures/sql/data.sql", "vendor/riddle/spec/fixtures/sql/structure.sql", "vendor/riddle/spec/functional/excerpt_spec.rb", "vendor/riddle/spec/functional/search_spec.rb", "vendor/riddle/spec/functional/update_spec.rb", "vendor/riddle/spec/spec_helper.rb", "vendor/riddle/spec/sphinx_helper.rb", "vendor/riddle/spec/unit/client_spec.rb", "vendor/riddle/spec/unit/filter_spec.rb", "vendor/riddle/spec/unit/message_spec.rb", "vendor/riddle/spec/unit/response_spec.rb", "vendor/will_paginate/LICENSE", "ultrasphinx.gemspec"]
|
17
17
|
s.has_rdoc = true
|
18
18
|
s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/}
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
s.rubyforge_project = %q{fauna}
|
21
|
-
s.rubygems_version = %q{0.9.
|
21
|
+
s.rubygems_version = %q{0.9.5}
|
22
22
|
s.summary = %q{Ruby on Rails configurator and client to the Sphinx fulltext search engine.}
|
23
23
|
s.test_files = ["test/test_all.rb"]
|
24
24
|
|
File without changes
|
@@ -0,0 +1,60 @@
|
|
1
|
+
This client has been written to interface with Sphinx[http://sphinxsearch.com/]. It is written by
|
2
|
+
{Pat Allan}[http://freelancing-gods.com], and has been influenced by both Dmytro Shteflyuk's Ruby
|
3
|
+
client and the original PHP client - credit where credit's due, after all.
|
4
|
+
|
5
|
+
It does not follow the same syntax as those two, though (not much point writing this otherwise) -
|
6
|
+
opting for a more Ruby-like structure.
|
7
|
+
|
8
|
+
While it doesn't (yet) exist as a gem, you can obtain the sourcecode via subversion. If you
|
9
|
+
are after a specific release, use the tag as follows:
|
10
|
+
|
11
|
+
svn co http://rails-oceania.googlecode.com/svn/patallan/riddle/tags/0.9.8-r871 riddle
|
12
|
+
|
13
|
+
Or for the most current, just use trunk:
|
14
|
+
|
15
|
+
svn co http://rails-oceania.googlecode.com/svn/patallan/riddle/trunk riddle
|
16
|
+
|
17
|
+
Please note that at the time of writing, only 0.9.8r871 is supported.
|
18
|
+
|
19
|
+
To get started, just instantiate a Client object:
|
20
|
+
|
21
|
+
client = Riddle::Client.new # defaults to localhost and port 3312
|
22
|
+
client = Riddle::Client.new "sphinxserver.domain.tld", 3333 # custom settings
|
23
|
+
|
24
|
+
And then set the parameters to what you want, before running a query:
|
25
|
+
|
26
|
+
client.match_mode = :extended
|
27
|
+
client.query "Pat Allan @state Victoria"
|
28
|
+
|
29
|
+
The results from a query are similar to the other clients - but here's the details. It's a hash with
|
30
|
+
the following keys:
|
31
|
+
|
32
|
+
* :matches
|
33
|
+
* :fields
|
34
|
+
* :attributes
|
35
|
+
* :attribute_names
|
36
|
+
* :words
|
37
|
+
* :total
|
38
|
+
* :total_found
|
39
|
+
* :time
|
40
|
+
* :status
|
41
|
+
* :warning (if appropriate)
|
42
|
+
* :error (if appropriate)
|
43
|
+
|
44
|
+
The key <tt>:matches</tt> returns an array of hashes - the actual search results. Each hash has the
|
45
|
+
document id (<tt>:doc</tt>), the result weighting (<tt>:weight</tt>), and a hash of the attributes for
|
46
|
+
the document (<tt>:attributes</tt>).
|
47
|
+
|
48
|
+
The <tt>:fields</tt> and <tt>:attribute_names</tt> keys return list of fields and attributes for the
|
49
|
+
documents. The key <tt>:attributes</tt> will return a hash of attribute name and type pairs, and
|
50
|
+
<tt>:words</tt> returns a hash of hashes representing the words from the search, with the number of
|
51
|
+
documents and hits for each, along the lines of:
|
52
|
+
|
53
|
+
results[:words]["Pat"] #=> {:docs => 12, :hits => 15}
|
54
|
+
|
55
|
+
<tt>:total</tt>, <tt>:total_found</tt> and <tt>:time</tt> return the number of matches available, the
|
56
|
+
total number of matches (which may be greater than the maximum available), and the time in milliseconds
|
57
|
+
that the query took to run.
|
58
|
+
|
59
|
+
<tt>:status</tt> is the error code for the query - and if there was a related warning, it will be under
|
60
|
+
the <tt>:warning</tt> key. Fatal errors will be described under <tt>:error</tt>.
|