ultrasphinx 1.9 → 1.11
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +6 -0
- data/DEPLOYMENT_NOTES +3 -1
- data/Manifest +10 -2
- data/RAKE_TASKS +2 -1
- data/README +6 -6
- data/Rakefile +27 -0
- data/examples/default.base +7 -2
- data/init.rb +1 -0
- data/lib/ultrasphinx/autoload.rb +0 -1
- data/lib/ultrasphinx/configure.rb +64 -36
- data/lib/ultrasphinx/core_extensions.rb +17 -2
- data/lib/ultrasphinx/fields.rb +33 -13
- data/lib/ultrasphinx/is_indexed.rb +32 -14
- data/lib/ultrasphinx/postgresql/concat_ws.sql +3 -3
- data/lib/ultrasphinx/postgresql/crc32.sql +1 -1
- data/lib/ultrasphinx/postgresql/group_concat.sql +1 -3
- data/lib/ultrasphinx/postgresql/hex_to_int.sql +1 -1
- data/lib/ultrasphinx/postgresql/unix_timestamp.sql +1 -1
- data/lib/ultrasphinx/search.rb +56 -6
- data/lib/ultrasphinx/search/internals.rb +88 -23
- data/lib/ultrasphinx/search/parser.rb +16 -2
- data/lib/ultrasphinx/spell.rb +2 -1
- data/lib/ultrasphinx/ultrasphinx.rb +43 -49
- data/tasks/ultrasphinx.rake +56 -16
- data/test/config/ultrasphinx/test.base +7 -2
- data/test/integration/app/app/controllers/addresses_controller.rb +9 -9
- data/test/integration/app/app/controllers/states_controller.rb +9 -9
- data/test/integration/app/app/models/category.rb +5 -0
- data/test/integration/app/app/models/geo/address.rb +1 -1
- data/test/integration/app/app/models/seller.rb +3 -3
- data/test/integration/app/app/views/addresses/edit.html.erb +2 -2
- data/test/integration/app/app/views/addresses/index.html.erb +2 -2
- data/test/integration/app/app/views/addresses/new.html.erb +1 -1
- data/test/integration/app/app/views/states/edit.html.erb +2 -2
- data/test/integration/app/app/views/states/index.html.erb +2 -2
- data/test/integration/app/app/views/states/new.html.erb +1 -1
- data/test/integration/app/app/views/users/index.html.erb +3 -3
- data/test/integration/app/config/environment.rb +1 -0
- data/test/integration/app/config/ultrasphinx/default.base +2 -2
- data/test/integration/app/config/ultrasphinx/development.conf.canonical +74 -50
- data/test/integration/app/db/migrate/007_add_lat_and_long_to_address.rb +3 -3
- data/test/integration/app/db/migrate/010_create_categories.rb +14 -0
- data/test/integration/app/db/migrate/011_categories_sellers.rb +15 -0
- data/test/integration/app/public/dispatch.cgi +0 -0
- data/test/integration/app/public/dispatch.fcgi +0 -0
- data/test/integration/app/public/dispatch.rb +0 -0
- data/test/integration/app/script/about +0 -0
- data/test/integration/app/script/breakpointer +0 -0
- data/test/integration/app/script/console +0 -0
- data/test/integration/app/script/destroy +0 -0
- data/test/integration/app/script/generate +0 -0
- data/test/integration/app/script/performance/benchmarker +0 -0
- data/test/integration/app/script/performance/profiler +0 -0
- data/test/integration/app/script/plugin +0 -0
- data/test/integration/app/script/process/inspector +0 -0
- data/test/integration/app/script/process/reaper +0 -0
- data/test/integration/app/script/process/spawner +0 -0
- data/test/integration/app/script/runner +0 -0
- data/test/integration/app/script/server +0 -0
- data/test/integration/app/test/fixtures/addresses.yml +77 -6
- data/test/integration/app/test/fixtures/categories.yml +101 -0
- data/test/integration/app/test/fixtures/categories_sellers.yml +29 -0
- data/test/integration/app/test/functional/addresses_controller_test.rb +9 -4
- data/test/integration/app/test/functional/sellers_controller_test.rb +9 -2
- data/test/integration/app/test/functional/states_controller_test.rb +10 -4
- data/test/integration/app/test/functional/users_controller_test.rb +7 -2
- data/test/integration/app/test/unit/address_test.rb +1 -1
- data/test/integration/app/test/unit/category_test.rb +8 -0
- data/test/integration/app/test/unit/country_test.rb +1 -1
- data/test/integration/app/test/unit/state_test.rb +1 -1
- data/test/integration/app/test/unit/user_test.rb +1 -1
- data/test/integration/delta_test.rb +13 -0
- data/test/integration/search_test.rb +80 -8
- data/test/profile/benchmark.rb +0 -0
- data/test/setup.rb +25 -7
- data/test/teardown.rb +13 -0
- data/test/test_helper.rb +3 -3
- data/ultrasphinx.gemspec +22 -43
- data/vendor/riddle/README +18 -4
- data/vendor/riddle/Rakefile +1 -0
- data/vendor/riddle/lib/riddle.rb +11 -5
- data/vendor/riddle/lib/riddle/client.rb +65 -20
- data/vendor/riddle/lib/riddle/client/response.rb +10 -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/comment.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/distinct.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/field_weights.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/filter.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/index_weights.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/keywords_with_hits.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/keywords_without_hits.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/phrase.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/rank_mode.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/weights.bin +0 -0
- data/vendor/riddle/spec/fixtures/data_generator.php +15 -0
- data/vendor/riddle/spec/fixtures/sphinx/configuration.erb +4 -4
- data/vendor/riddle/spec/fixtures/sphinxapi.php +118 -7
- data/vendor/riddle/spec/functional/keywords_spec.rb +40 -0
- data/vendor/riddle/spec/spec_helper.rb +1 -0
- data/vendor/riddle/spec/unit/client_spec.rb +26 -0
- metadata +38 -11
- metadata.gz.sig +0 -0
- data/test/integration/app/config/ultrasphinx/development.conf +0 -319
- data/test/integration/app/db/schema.rb +0 -56
data.tar.gz.sig
CHANGED
Binary file
|
data/CHANGELOG
CHANGED
@@ -1,4 +1,10 @@
|
|
1
1
|
|
2
|
+
v1.11. Update to Sphinx 0.9.8-rc2.
|
3
|
+
|
4
|
+
v1.10. Add geodistance support (Jeremy Seitz, Mark Lane). Move Postgres stored procedures into a migration generator (Lang Riley). Duplicate text :sortable columns so that they are also searchable.
|
5
|
+
|
6
|
+
v1.9.1. Add ultrasphinx:index:merge task for index merging, and a note in DEPLOYMENT_NOTES about how to use it.
|
7
|
+
|
2
8
|
v1.9. Delta indexing. ERb now supported in .base files. Allow setting the searched indexes at runtime.
|
3
9
|
|
4
10
|
v1.8.1. Use multifind/multiget for record loading; avoid using HashWithIndifferentAccess internally for speed; other minor performance improvements.
|
data/DEPLOYMENT_NOTES
CHANGED
@@ -17,13 +17,15 @@ It's easy to keep the search daemon and the indexer running in a production envi
|
|
17
17
|
|
18
18
|
*/6 * * * * bash -c 'cd /path/to/production/current/; RAILS_ENV=production \
|
19
19
|
rake ultrasphinx:index:delta >> /log/ultrasphinx-index.log 2>&1'
|
20
|
-
1 4 * * *
|
20
|
+
1 4 * * * bash -c 'cd /path/to/production/current/; RAILS_ENV=production \
|
21
21
|
rake ultrasphinx:index:main >> /log/ultrasphinx-index.log 2>&1'
|
22
22
|
*/3 * * * * bash -c 'cd /path/to/production/current/; RAILS_ENV=production \
|
23
23
|
rake ultrasphinx:daemon:start >> /log/ultrasphinx-daemon.log 2>&1'
|
24
24
|
|
25
25
|
The first line reindexes the delta index every 10 minutes. The second line reindexes the main index once a day at 4am. The third line will try to restart the search daemon every three minutes. If it's already running, nothing happens.
|
26
26
|
|
27
|
+
Note that you can use <tt>ultrasphinx:index:merge</tt> in place of <tt>ultrasphinx:index:main</tt>. It will be faster, but will not remove deleted records from the index.
|
28
|
+
|
27
29
|
Of course if you don't have any models with deltas, don't include the <tt>ultrasphinx:index:delta</tt> task.
|
28
30
|
|
29
31
|
If you are under severe memory limitations you might want to manage the daemon with Monit instead, so you can keep a closer eye on it. The search daemon is extremely reliable, so don't bother with fancy monitoring infrastructure unless you're sure you need it.
|
data/Manifest
CHANGED
@@ -37,6 +37,7 @@ test/integration/app/app/helpers/application_helper.rb
|
|
37
37
|
test/integration/app/app/helpers/sellers_helper.rb
|
38
38
|
test/integration/app/app/helpers/states_helper.rb
|
39
39
|
test/integration/app/app/helpers/users_helper.rb
|
40
|
+
test/integration/app/app/models/category.rb
|
40
41
|
test/integration/app/app/models/geo/address.rb
|
41
42
|
test/integration/app/app/models/geo/country.rb
|
42
43
|
test/integration/app/app/models/geo/state.rb
|
@@ -71,7 +72,6 @@ test/integration/app/config/environments/test.rb
|
|
71
72
|
test/integration/app/config/locomotive.yml
|
72
73
|
test/integration/app/config/routes.rb
|
73
74
|
test/integration/app/config/ultrasphinx/default.base
|
74
|
-
test/integration/app/config/ultrasphinx/development.conf
|
75
75
|
test/integration/app/config/ultrasphinx/development.conf.canonical
|
76
76
|
test/integration/app/db/migrate/001_create_users.rb
|
77
77
|
test/integration/app/db/migrate/002_create_sellers.rb
|
@@ -82,7 +82,8 @@ test/integration/app/db/migrate/006_add_deleted_to_user.rb
|
|
82
82
|
test/integration/app/db/migrate/007_add_lat_and_long_to_address.rb
|
83
83
|
test/integration/app/db/migrate/008_add_mission_statement_to_seller.rb
|
84
84
|
test/integration/app/db/migrate/009_create_countries.rb
|
85
|
-
test/integration/app/db/
|
85
|
+
test/integration/app/db/migrate/010_create_categories.rb
|
86
|
+
test/integration/app/db/migrate/011_categories_sellers.rb
|
86
87
|
test/integration/app/doc/README_FOR_APP
|
87
88
|
test/integration/app/public/404.html
|
88
89
|
test/integration/app/public/500.html
|
@@ -115,6 +116,8 @@ test/integration/app/script/process/spawner
|
|
115
116
|
test/integration/app/script/runner
|
116
117
|
test/integration/app/script/server
|
117
118
|
test/integration/app/test/fixtures/addresses.yml
|
119
|
+
test/integration/app/test/fixtures/categories.yml
|
120
|
+
test/integration/app/test/fixtures/categories_sellers.yml
|
118
121
|
test/integration/app/test/fixtures/countries.yml
|
119
122
|
test/integration/app/test/fixtures/sellers.yml
|
120
123
|
test/integration/app/test/fixtures/states.yml
|
@@ -125,6 +128,7 @@ test/integration/app/test/functional/states_controller_test.rb
|
|
125
128
|
test/integration/app/test/functional/users_controller_test.rb
|
126
129
|
test/integration/app/test/test_helper.rb
|
127
130
|
test/integration/app/test/unit/address_test.rb
|
131
|
+
test/integration/app/test/unit/category_test.rb
|
128
132
|
test/integration/app/test/unit/country_test.rb
|
129
133
|
test/integration/app/test/unit/seller_test.rb
|
130
134
|
test/integration/app/test/unit/state_test.rb
|
@@ -153,6 +157,7 @@ vendor/riddle/README
|
|
153
157
|
vendor/riddle/spec/fixtures/data/anchor.bin
|
154
158
|
vendor/riddle/spec/fixtures/data/any.bin
|
155
159
|
vendor/riddle/spec/fixtures/data/boolean.bin
|
160
|
+
vendor/riddle/spec/fixtures/data/comment.bin
|
156
161
|
vendor/riddle/spec/fixtures/data/distinct.bin
|
157
162
|
vendor/riddle/spec/fixtures/data/field_weights.bin
|
158
163
|
vendor/riddle/spec/fixtures/data/filter.bin
|
@@ -166,6 +171,8 @@ vendor/riddle/spec/fixtures/data/filter_range_exclude.bin
|
|
166
171
|
vendor/riddle/spec/fixtures/data/group.bin
|
167
172
|
vendor/riddle/spec/fixtures/data/index.bin
|
168
173
|
vendor/riddle/spec/fixtures/data/index_weights.bin
|
174
|
+
vendor/riddle/spec/fixtures/data/keywords_with_hits.bin
|
175
|
+
vendor/riddle/spec/fixtures/data/keywords_without_hits.bin
|
169
176
|
vendor/riddle/spec/fixtures/data/phrase.bin
|
170
177
|
vendor/riddle/spec/fixtures/data/rank_mode.bin
|
171
178
|
vendor/riddle/spec/fixtures/data/simple.bin
|
@@ -179,6 +186,7 @@ vendor/riddle/spec/fixtures/sql/conf.example.yml
|
|
179
186
|
vendor/riddle/spec/fixtures/sql/data.sql
|
180
187
|
vendor/riddle/spec/fixtures/sql/structure.sql
|
181
188
|
vendor/riddle/spec/functional/excerpt_spec.rb
|
189
|
+
vendor/riddle/spec/functional/keywords_spec.rb
|
182
190
|
vendor/riddle/spec/functional/search_spec.rb
|
183
191
|
vendor/riddle/spec/functional/update_spec.rb
|
184
192
|
vendor/riddle/spec/spec_helper.rb
|
data/RAKE_TASKS
CHANGED
@@ -7,6 +7,7 @@ These Rake tasks are made available to your Rails app:
|
|
7
7
|
<tt>ultrasphinx:index</tt>:: Reindex and rotate all indexes.
|
8
8
|
<tt>ultrasphinx:index:delta</tt>:: Reindex and rotate the delta index.
|
9
9
|
<tt>ultrasphinx:index:main</tt>:: Reindex and rotate the main index.
|
10
|
+
<tt>ultrasphinx:index:merge</tt>:: Merge the delta index into the main index.
|
10
11
|
<tt>ultrasphinx:daemon:restart</tt>:: Restart the search daemon.
|
11
12
|
<tt>ultrasphinx:daemon:start</tt>:: Start the search daemon.
|
12
13
|
<tt>ultrasphinx:daemon:stop</tt>:: Stop the search daemon.
|
@@ -14,4 +15,4 @@ These Rake tasks are made available to your Rails app:
|
|
14
15
|
<tt>ultrasphinx:spelling:build</tt>:: Rebuild the custom spelling dictionary. You may need to use <tt>sudo</tt> if your Aspell folder is not writable by the app user.
|
15
16
|
<tt>ultrasphinx:bootstrap</tt>:: Bootstrap a full Sphinx environment by running configure, index, then daemon:start.
|
16
17
|
|
17
|
-
All tasks have shortcuts. Use <tt>us:conf</tt>, <tt>us:index</tt>, <tt>us:main</tt>, <tt>us:delta</tt>, <tt>us:restart</tt>, <tt>us:start</tt>, <tt>us:stop</tt>, <tt>us:stat</tt>, <tt>us:spell</tt>, and <tt>us:boot</tt>.
|
18
|
+
All tasks have shortcuts. Use <tt>us:conf</tt>, <tt>us:index</tt>, <tt>us:main</tt>, <tt>us:delta</tt>, <tt>us:merge</tt>, <tt>us:restart</tt>, <tt>us:start</tt>, <tt>us:stop</tt>, <tt>us:stat</tt>, <tt>us:spell</tt>, and <tt>us:boot</tt>.
|
data/README
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
|
2
1
|
Ultrasphinx
|
3
2
|
|
4
3
|
Ruby on Rails configurator and client to the Sphinx full text search engine.
|
@@ -14,7 +13,7 @@ If you use this software, please {make a donation}[http://blog.evanweaver.com/do
|
|
14
13
|
== Requirements
|
15
14
|
|
16
15
|
* MySQL 5.0, or PostgreSQL 8.2
|
17
|
-
* Sphinx 0.9.8-
|
16
|
+
* Sphinx 0.9.8-rc2
|
18
17
|
* Rails 2.0.2
|
19
18
|
|
20
19
|
More recent versions than listed are usually ok.
|
@@ -25,13 +24,14 @@ Sphinx/Ultrasphinx is the fastest and most stable Rails fulltext search solution
|
|
25
24
|
|
26
25
|
Features include:
|
27
26
|
|
28
|
-
* searching and ranking across
|
27
|
+
* searching and ranking across multiple models
|
29
28
|
* delta index support
|
30
29
|
* excerpt highlighting
|
31
30
|
* Google-style query parser
|
32
31
|
* spellcheck
|
33
32
|
* faceting on text, date, and numeric fields
|
34
|
-
* field weighting, merging, and
|
33
|
+
* field weighting, merging, and aliasing
|
34
|
+
* geodistance
|
35
35
|
* <tt>belongs_to</tt> and <tt>has_many</tt> includes
|
36
36
|
* drop-in compatibility with will_paginate[http://err.lighthouseapp.com/projects/466/home]
|
37
37
|
* drop-in compatibility with Interlock[http://blog.evanweaver.com/files/doc/fauna/interlock/]
|
@@ -50,7 +50,7 @@ You also need the <tt>chronic</tt> gem:
|
|
50
50
|
sudo gem install chronic
|
51
51
|
|
52
52
|
Then, install the plugin:
|
53
|
-
script/plugin install
|
53
|
+
script/plugin install git://github.com/fauna/ultrasphinx.git
|
54
54
|
|
55
55
|
Next, copy the <tt>examples/default.base</tt> file to <tt>RAILS_ROOT/config/ultrasphinx/default.base</tt>. This file sets up the Sphinx daemon options such as port, host, and index location.
|
56
56
|
|
@@ -124,7 +124,7 @@ See DEPLOYMENT_NOTES[link:files/DEPLOYMENT_NOTES.html].
|
|
124
124
|
|
125
125
|
Note that since Ultrasphinx preloads indexed models, you need to make sure those models have their own dependencies in place early in the boot process. This may require adjusting the general plugin load order or moving monkey-patches from <tt>lib/</tt> to <tt>vendor/plugins/</tt>.
|
126
126
|
|
127
|
-
PostgreSQL 8.2 and higher are well supported. However, make sure
|
127
|
+
PostgreSQL 8.2 and higher are well supported. However, make sure the stored procedure migration gets generated correctly. If you did not install the plugin via <tt>script/install</tt>, run <tt>script/generate ultrasphinx_migration</tt> by hand.
|
128
128
|
|
129
129
|
== Reporting problems
|
130
130
|
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
require 'echoe'
|
3
|
+
|
4
|
+
Echoe.new("ultrasphinx") do |p|
|
5
|
+
p.project = "fauna"
|
6
|
+
p.summary = "Ruby on Rails configurator and client to the Sphinx fulltext search engine."
|
7
|
+
p.url = "http://blog.evanweaver.com/files/doc/fauna/ultrasphinx/"
|
8
|
+
p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
|
9
|
+
p.rdoc_pattern = /is_indexed.rb|search.rb|spell.rb|ultrasphinx.rb|^README|TODO|DEPLOY|RAKE_TASKS|CHANGELOG|^LICENSE/
|
10
|
+
p.dependencies = "chronic"
|
11
|
+
p.test_pattern = ["test/integration/*.rb", "test/unit/*.rb"]
|
12
|
+
p.rcov_options << '--include-file test\/integration\/app\/vendor\/plugins\/ultrasphinx\/lib\/.*\.rb --include-file '
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Run all the tests for every database adapter"
|
16
|
+
task "test_all" do
|
17
|
+
['mysql', 'postgresql'].each do |adapter|
|
18
|
+
ENV['DB'] = adapter
|
19
|
+
ENV['PRODUCTION'] = nil
|
20
|
+
STDERR.puts "#{'='*80}\nDevelopment mode for #{adapter}\n#{'='*80}"
|
21
|
+
system("rake test:multi_rails:all")
|
22
|
+
|
23
|
+
ENV['PRODUCTION'] = '1'
|
24
|
+
STDERR.puts "#{'='*80}\nProduction mode for #{adapter}\n#{'='*80}"
|
25
|
+
system("rake test:multi_rails:all")
|
26
|
+
end
|
27
|
+
end
|
data/examples/default.base
CHANGED
@@ -34,7 +34,7 @@ searchd
|
|
34
34
|
{
|
35
35
|
# What interface the search daemon should listen on and where to store its logs
|
36
36
|
address = 0.0.0.0
|
37
|
-
port =
|
37
|
+
port = 3313
|
38
38
|
seamless_rotate = 1
|
39
39
|
log = <%= path %>log/searchd.log
|
40
40
|
query_log = <%= path %>log/query.log
|
@@ -52,7 +52,7 @@ client
|
|
52
52
|
|
53
53
|
# How your application connects to the search daemon (not necessarily the same as above)
|
54
54
|
server_host = localhost
|
55
|
-
server_port =
|
55
|
+
server_port = 3313
|
56
56
|
}
|
57
57
|
|
58
58
|
# Individual SQL source options
|
@@ -79,6 +79,11 @@ index
|
|
79
79
|
# Enable these if you need wildcard searching. They will slow down indexing significantly.
|
80
80
|
# min_infix_len = 1
|
81
81
|
# enable_star = 1
|
82
|
+
|
83
|
+
# # URL search options
|
84
|
+
# # add " @, /, :," before " a-z," in the charset_table and uncomment prefix_fields
|
85
|
+
# to seach URL and email addresses
|
86
|
+
# prefix_fields = url, domain
|
82
87
|
|
83
88
|
charset_type = utf-8 # or sbcs (Single Byte Character Set)
|
84
89
|
charset_table = 0..9, A..Z->a..z, -, _, ., &, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F,U+C5->U+E5, U+E5, U+C4->U+E4, U+E4, U+D6->U+F6, U+F6, U+16B, U+0c1->a, U+0c4->a, U+0c9->e, U+0cd->i, U+0d3->o, U+0d4->o, U+0da->u, U+0dd->y, U+0e1->a, U+0e4->a, U+0e9->e, U+0ed->i, U+0f3->o, U+0f4->o, U+0fa->u, U+0fd->y, U+104->U+105, U+105, U+106->U+107, U+10c->c, U+10d->c, U+10e->d, U+10f->d, U+116->U+117, U+117, U+118->U+119, U+11a->e, U+11b->e, U+12E->U+12F, U+12F, U+139->l, U+13a->l, U+13d->l, U+13e->l, U+141->U+142, U+142, U+143->U+144, U+144,U+147->n, U+148->n, U+154->r, U+155->r, U+158->r, U+159->r, U+15A->U+15B, U+15B, U+160->s, U+160->U+161, U+161->s, U+164->t, U+165->t, U+16A->U+16B, U+16B, U+16e->u, U+16f->u, U+172->U+173, U+173, U+179->U+17A, U+17A, U+17B->U+17C, U+17C, U+17d->z, U+17e->z,
|
data/init.rb
CHANGED
data/lib/ultrasphinx/autoload.rb
CHANGED
@@ -6,7 +6,6 @@ class Rails::Initializer
|
|
6
6
|
def after_initialize_with_ultrasphinx_configuration
|
7
7
|
after_initialize_without_ultrasphinx_configuration
|
8
8
|
Ultrasphinx::Configure.load_constants
|
9
|
-
Ultrasphinx.verify_database_name
|
10
9
|
end
|
11
10
|
|
12
11
|
alias_method_chain :after_initialize, :ultrasphinx_configuration
|
@@ -16,21 +16,20 @@ module Ultrasphinx
|
|
16
16
|
filename = filename[0..-4]
|
17
17
|
begin
|
18
18
|
File.basename(filename).camelize.constantize
|
19
|
-
rescue NameError => e
|
19
|
+
rescue LoadError, NameError => e
|
20
20
|
filename.camelize.constantize
|
21
21
|
end
|
22
22
|
end
|
23
23
|
rescue Object => e
|
24
|
-
say "warning:
|
25
|
-
say e.
|
26
|
-
#say e.backtrace.join("\n") if RAILS_ENV == "development"
|
24
|
+
say "warning: critical autoload error on #{filename}; try referencing \"#{filename.camelize}\" directly in the console"
|
25
|
+
say e.backtrace.join("\n") if RAILS_ENV == "development"
|
27
26
|
end
|
28
27
|
end
|
29
28
|
end
|
30
29
|
end
|
31
30
|
|
32
31
|
# Build the field-to-type mappings.
|
33
|
-
Fields.instance.configure(MODEL_CONFIGURATION)
|
32
|
+
Ultrasphinx::Fields.instance.configure(MODEL_CONFIGURATION)
|
34
33
|
end
|
35
34
|
|
36
35
|
|
@@ -40,7 +39,9 @@ module Ultrasphinx
|
|
40
39
|
load_constants
|
41
40
|
|
42
41
|
say "rebuilding configurations for #{RAILS_ENV} environment"
|
43
|
-
|
42
|
+
# stable sort classes by name rather than rely on hash order
|
43
|
+
model_list = MODEL_CONFIGURATION.keys.sort
|
44
|
+
say "available models are #{model_list.to_sentence}"
|
44
45
|
File.open(CONF_PATH, "w") do |conf|
|
45
46
|
conf.puts global_header
|
46
47
|
say "generating SQL"
|
@@ -49,9 +50,8 @@ module Ultrasphinx
|
|
49
50
|
sources = []
|
50
51
|
cached_groups = Fields.instance.groups.join("\n")
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
model, options = model_and_options
|
53
|
+
model_list.each_with_index do |model, class_id|
|
54
|
+
options = MODEL_CONFIGURATION[model]
|
55
55
|
klass = model.constantize
|
56
56
|
source = "#{model.tableize.gsub('/', '__')}_#{index}"
|
57
57
|
|
@@ -89,13 +89,16 @@ module Ultrasphinx
|
|
89
89
|
def setup_source_database(klass)
|
90
90
|
# Supporting Postgres now
|
91
91
|
connection_settings = klass.connection.instance_variable_get("@config")
|
92
|
+
raise ConfigurationError, "Unsupported database adapter" unless connection_settings || defined?(JRUBY_VERSION)
|
92
93
|
|
93
94
|
adapter_defaults = DEFAULTS[ADAPTER]
|
94
95
|
raise ConfigurationError, "Unsupported database adapter" unless adapter_defaults
|
95
96
|
|
96
97
|
conf = [adapter_defaults]
|
97
98
|
connection_settings.reverse_merge(CONNECTION_DEFAULTS).each do |key, value|
|
98
|
-
|
99
|
+
if CONFIG_MAP[key] && !SOURCE_SETTINGS[CONFIG_MAP[key]]
|
100
|
+
conf << "#{CONFIG_MAP[key]} = #{value}"
|
101
|
+
end
|
99
102
|
end
|
100
103
|
conf.sort.join("\n")
|
101
104
|
end
|
@@ -114,8 +117,14 @@ module Ultrasphinx
|
|
114
117
|
# Warning about the sortable problem
|
115
118
|
# XXX Kind of in an odd place, but I want to happen at index time
|
116
119
|
Ultrasphinx.say "warning; text sortable columns on #{klass.name} will return wrong results with partial delta indexing"
|
117
|
-
end
|
118
|
-
|
120
|
+
end
|
121
|
+
|
122
|
+
delta = INDEXER_SETTINGS['delta']
|
123
|
+
if delta
|
124
|
+
string = "#{source_string} > #{SQL_FUNCTIONS[ADAPTER]['delta']._interpolate(delta)}";
|
125
|
+
else
|
126
|
+
raise ConfigurationError, "No 'indexer { delta }' setting specified in '#{BASE_PATH}'"
|
127
|
+
end
|
119
128
|
else
|
120
129
|
Ultrasphinx.say "warning; #{klass.name} will reindex the entire table during delta indexing"
|
121
130
|
end
|
@@ -123,8 +132,18 @@ module Ultrasphinx
|
|
123
132
|
end
|
124
133
|
|
125
134
|
|
126
|
-
def setup_source_arrays(index, klass, fields, class_id, conditions)
|
127
|
-
|
135
|
+
def setup_source_arrays(index, klass, fields, class_id, conditions, order)
|
136
|
+
if((klass.column_names.include? klass.inheritance_column) and (klass.superclass != ActiveRecord::Base))
|
137
|
+
if conditions.nil?
|
138
|
+
conditions = ""
|
139
|
+
else
|
140
|
+
conditions += " AND "
|
141
|
+
end
|
142
|
+
conditions += "#{klass.table_name}.#{klass.inheritance_column} = '#{klass.name.to_s}' "
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
condition_strings = Array(conditions).map do |condition|
|
128
147
|
"(#{condition})"
|
129
148
|
end
|
130
149
|
|
@@ -132,7 +151,7 @@ module Ultrasphinx
|
|
132
151
|
"(#{klass.table_name}.#{klass.primary_key} * #{MODEL_CONFIGURATION.size} + #{class_id}) AS id",
|
133
152
|
"#{class_id} AS class_id", "'#{klass.name}' AS class"]
|
134
153
|
remaining_columns = fields.types.keys - ["class", "class_id"]
|
135
|
-
[column_strings, [], condition_strings, [], false, remaining_columns]
|
154
|
+
[column_strings, [], condition_strings, [], false, remaining_columns, order]
|
136
155
|
end
|
137
156
|
|
138
157
|
|
@@ -154,9 +173,9 @@ module Ultrasphinx
|
|
154
173
|
|
155
174
|
def build_source(index, fields, model, options, class_id, klass, source, groups)
|
156
175
|
|
157
|
-
column_strings, join_strings, condition_strings, group_bys, use_distinct, remaining_columns =
|
176
|
+
column_strings, join_strings, condition_strings, group_bys, use_distinct, remaining_columns, order =
|
158
177
|
setup_source_arrays(
|
159
|
-
index, klass, fields, class_id, options['conditions'])
|
178
|
+
index, klass, fields, class_id, options['conditions'], options['order'])
|
160
179
|
|
161
180
|
delta_condition =
|
162
181
|
build_delta_condition(
|
@@ -182,18 +201,18 @@ module Ultrasphinx
|
|
182
201
|
SOURCE_SETTINGS._to_conf_string,
|
183
202
|
setup_source_database(klass),
|
184
203
|
range_select_string(klass, delta_condition),
|
185
|
-
build_query(klass, column_strings, join_strings, condition_strings, use_distinct, group_bys),
|
204
|
+
build_query(klass, column_strings, join_strings, condition_strings, use_distinct, group_bys, order),
|
186
205
|
"\n" + groups,
|
187
206
|
query_info_string(klass, class_id),
|
188
207
|
"}\n\n"]
|
189
208
|
end
|
190
209
|
|
191
210
|
|
192
|
-
def build_query(klass, column_strings, join_strings, condition_strings, use_distinct, group_bys)
|
211
|
+
def build_query(klass, column_strings, join_strings, condition_strings, use_distinct, group_bys, order)
|
193
212
|
|
194
213
|
primary_key = "#{klass.table_name}.#{klass.primary_key}"
|
195
214
|
group_bys = case ADAPTER
|
196
|
-
when 'mysql'
|
215
|
+
when 'mysql', 'jdbcmysql'
|
197
216
|
primary_key
|
198
217
|
when 'postgresql'
|
199
218
|
# Postgres is very fussy about GROUP_BY
|
@@ -211,7 +230,8 @@ module Ultrasphinx
|
|
211
230
|
join_strings.uniq,
|
212
231
|
"WHERE #{primary_key} >= $start AND #{primary_key} <= $end",
|
213
232
|
condition_strings.uniq.map {|condition| "AND #{condition}" },
|
214
|
-
"GROUP BY #{group_bys}"
|
233
|
+
"GROUP BY #{group_bys}",
|
234
|
+
("ORDER BY #{order}" if order)
|
215
235
|
].flatten.compact.join(" ")
|
216
236
|
end
|
217
237
|
|
@@ -225,10 +245,10 @@ module Ultrasphinx
|
|
225
245
|
|
226
246
|
|
227
247
|
def build_regular_fields(klass, fields, entries, column_strings, join_strings, group_bys, remaining_columns)
|
228
|
-
entries.to_a.each do |entry|
|
229
|
-
source_string = "#{entry['table_alias']}.#{entry['field']}"
|
248
|
+
entries.to_a.each do |entry|
|
249
|
+
source_string = "#{entry['table_alias']}.#{entry['field']}"
|
230
250
|
group_bys << source_string
|
231
|
-
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], column_strings, remaining_columns)
|
251
|
+
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], entry['sortable'], column_strings, remaining_columns)
|
232
252
|
end
|
233
253
|
|
234
254
|
[column_strings, join_strings, group_bys, remaining_columns]
|
@@ -242,7 +262,7 @@ module Ultrasphinx
|
|
242
262
|
association = get_association(klass, entry)
|
243
263
|
|
244
264
|
# You can use 'class_name' and 'association_sql' to associate to a model that doesn't actually
|
245
|
-
# have an association
|
265
|
+
# have an association.
|
246
266
|
join_klass = association ? association.class_name.constantize : entry['class_name'].constantize
|
247
267
|
|
248
268
|
raise ConfigurationError, "Unknown association from #{klass} to #{entry['class_name'] || entry['association_name']}" if not association and not entry['association_sql']
|
@@ -259,8 +279,8 @@ module Ultrasphinx
|
|
259
279
|
end
|
260
280
|
|
261
281
|
source_string = "#{entry['table_alias']}.#{entry['field']}"
|
262
|
-
group_bys << source_string
|
263
|
-
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], column_strings, remaining_columns)
|
282
|
+
group_bys << source_string unless entry['dont_group_by']
|
283
|
+
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], entry['sortable'], column_strings, remaining_columns)
|
264
284
|
end
|
265
285
|
|
266
286
|
[column_strings, join_strings, group_bys, remaining_columns]
|
@@ -272,26 +292,28 @@ module Ultrasphinx
|
|
272
292
|
if entry['field']
|
273
293
|
# Group concats
|
274
294
|
|
275
|
-
# Only has_many's or explicit sql right now
|
295
|
+
# Only has_many's or explicit sql right now.
|
276
296
|
association = get_association(klass, entry)
|
277
297
|
|
278
298
|
# You can use 'class_name' and 'association_sql' to associate to a model that doesn't actually
|
279
|
-
# have an association
|
299
|
+
# have an association. The automatic choice of a table alias chosen might be kind of strange.
|
280
300
|
join_klass = association ? association.class_name.constantize : entry['class_name'].constantize
|
281
301
|
|
282
302
|
join_strings = install_join_unless_association_sql(entry['association_sql'], nil, join_strings) do
|
283
|
-
# XXX
|
303
|
+
# XXX The foreign key is not verified for polymorphic relationships.
|
284
304
|
association = get_association(klass, entry)
|
285
305
|
"LEFT OUTER JOIN #{join_klass.table_name} AS #{entry['table_alias']} ON #{klass.table_name}.#{klass.primary_key} = #{entry['table_alias']}.#{association.primary_key_name}" +
|
286
|
-
|
306
|
+
# XXX Is this valid?
|
307
|
+
(entry['conditions'] ? " AND (#{entry['conditions']})" : "")
|
287
308
|
end
|
288
309
|
|
289
310
|
source_string = "#{entry['table_alias']}.#{entry['field']}"
|
311
|
+
order_string = ("ORDER BY #{entry['order']}" if entry['order'])
|
290
312
|
# We are using the field in an aggregate, so we don't want to add it to group_bys
|
291
|
-
source_string = SQL_FUNCTIONS[ADAPTER]['group_concat']._interpolate(source_string)
|
313
|
+
source_string = SQL_FUNCTIONS[ADAPTER]['group_concat']._interpolate(source_string, order_string)
|
292
314
|
use_distinct = true
|
293
315
|
|
294
|
-
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], column_strings, remaining_columns)
|
316
|
+
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], entry['sortable'], column_strings, remaining_columns)
|
295
317
|
|
296
318
|
elsif entry['fields']
|
297
319
|
# Regular concats
|
@@ -301,7 +323,7 @@ module Ultrasphinx
|
|
301
323
|
group_bys << subsource_string
|
302
324
|
end.join(', ') + ")"
|
303
325
|
|
304
|
-
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], column_strings, remaining_columns)
|
326
|
+
column_strings, remaining_columns = install_field(fields, source_string, entry['as'], entry['function_sql'], entry['facet'], entry['sortable'], column_strings, remaining_columns)
|
305
327
|
|
306
328
|
else
|
307
329
|
raise ConfigurationError, "Invalid concatenate parameters for #{model}: #{entry.inspect}."
|
@@ -311,7 +333,7 @@ module Ultrasphinx
|
|
311
333
|
[column_strings, join_strings, group_bys, use_distinct, remaining_columns]
|
312
334
|
end
|
313
335
|
|
314
|
-
|
336
|
+
|
315
337
|
def build_index(index, sources)
|
316
338
|
["\n# Index configuration\n\n",
|
317
339
|
"index #{index}\n{",
|
@@ -323,12 +345,18 @@ module Ultrasphinx
|
|
323
345
|
end
|
324
346
|
|
325
347
|
|
326
|
-
def install_field(fields, source_string, as, function_sql, with_facet, column_strings, remaining_columns)
|
348
|
+
def install_field(fields, source_string, as, function_sql, with_facet, with_sortable, column_strings, remaining_columns)
|
327
349
|
source_string = function_sql._interpolate(source_string) if function_sql
|
328
350
|
|
329
351
|
column_strings << fields.cast(source_string, as)
|
330
352
|
remaining_columns.delete(as)
|
331
353
|
|
354
|
+
# Generate duplicate text fields for sorting
|
355
|
+
if with_sortable
|
356
|
+
column_strings << fields.cast(source_string, "#{as}_sortable")
|
357
|
+
remaining_columns.delete("#{as}_sortable")
|
358
|
+
end
|
359
|
+
|
332
360
|
# Generate hashed integer fields for text grouping
|
333
361
|
if with_facet
|
334
362
|
column_strings << "#{SQL_FUNCTIONS[ADAPTER]['hash']._interpolate(source_string)} AS #{as}_facet"
|