ultrasphinx 1.8 → 1.9
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 +1 -3
- data/CHANGELOG +4 -0
- data/DEPLOYMENT_NOTES +7 -3
- data/Manifest +10 -0
- data/RAKE_TASKS +4 -2
- data/README +35 -18
- data/TODO +0 -1
- data/examples/default.base +24 -19
- data/lib/ultrasphinx.rb +1 -1
- data/lib/ultrasphinx/configure.rb +66 -25
- data/lib/ultrasphinx/core_extensions.rb +10 -1
- data/lib/ultrasphinx/is_indexed.rb +49 -6
- data/lib/ultrasphinx/search.rb +81 -69
- data/lib/ultrasphinx/search/internals.rb +61 -38
- data/lib/ultrasphinx/search/parser.rb +17 -7
- data/lib/ultrasphinx/ultrasphinx.rb +69 -16
- data/tasks/ultrasphinx.rake +47 -29
- data/test/config/ultrasphinx/test.base +50 -21
- data/test/integration/app/app/models/geo/address.rb +2 -1
- data/test/integration/app/app/models/person/user.rb +12 -3
- data/test/integration/app/app/models/seller.rb +2 -1
- data/test/integration/app/config/environment.rb +2 -0
- data/test/integration/app/config/ultrasphinx/default.base +16 -8
- data/test/integration/app/config/ultrasphinx/development.conf +319 -0
- data/test/integration/app/config/ultrasphinx/development.conf.canonical +152 -24
- data/test/integration/app/db/schema.rb +56 -0
- data/test/integration/app/test/fixtures/sellers.yml +1 -1
- data/test/integration/app/test/fixtures/users.yml +1 -1
- data/test/integration/app/test/unit/country_test.rb +8 -0
- data/test/integration/delta_test.rb +39 -0
- data/test/integration/search_test.rb +60 -1
- data/test/integration/spell_test.rb +6 -2
- data/test/profile/benchmark.rb +44 -0
- data/test/test_helper.rb +6 -1
- data/test/unit/parser_test.rb +21 -2
- data/ultrasphinx.gemspec +4 -4
- data/vendor/riddle/README +2 -2
- data/vendor/riddle/lib/riddle.rb +1 -1
- data/vendor/riddle/lib/riddle/client.rb +45 -10
- 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/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/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/update_simple.bin +0 -0
- data/vendor/riddle/spec/fixtures/data/weights.bin +0 -0
- data/vendor/riddle/spec/fixtures/data_generator.php +130 -0
- data/vendor/riddle/spec/fixtures/sphinxapi.php +1066 -0
- data/vendor/riddle/spec/spec_helper.rb +1 -0
- data/vendor/riddle/spec/unit/client_spec.rb +18 -4
- metadata +12 -2
- metadata.gz.sig +0 -0
    
        data.tar.gz.sig
    CHANGED
    
    | @@ -1,3 +1 @@ | |
| 1 | 
            -
            U | 
| 2 | 
            -
            �%�g($�.���#`������h�W����z\_{wo�N��@rf����4�EAʭ?��l��������П�;�g���͠v���
         | 
| 3 | 
            -
            �[�>A���"F������3d|�[4�Z������z�mD��E$`sˎ���b�+��*Q�ߩp�R`��#~"��B�T��
         | 
| 1 | 
            +
            (Qr��u'�9���_�U؇�4]�;��x�*����oA����[Y�?�.0�,7�˗�K�ƛ8@<�j�':��4|�F����)�ɝ�}a�m��g8E#�D^+(aX]LM�k�|��EL_P�b<�JU$����>��kr��>�Pp!�g	��m�Xy�T� �ZI��M�DB&�K�w����E���W�~�6��=���qO�	v$��1!��u�Qȷ�n��5A�ٳ����=V��lz6Il
         | 
    
        data/CHANGELOG
    CHANGED
    
    | @@ -1,4 +1,8 @@ | |
| 1 1 |  | 
| 2 | 
            +
            v1.9. Delta indexing. ERb now supported in .base files. Allow setting the searched indexes at runtime.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            v1.8.1. Use multifind/multiget for record loading; avoid using HashWithIndifferentAccess internally for speed; other minor performance improvements.
         | 
| 5 | 
            +
             | 
| 2 6 | 
             
            v1.8. Update client for compatibility with Sphinx 0.9.8 r1112. This is a breaking release! You need to update Sphinx along with Ultrasphinx. Float range bugfix; text faceting on association_include bugfix. Postgres users, please note that the return type of CRC32() has changed to bigint.
         | 
| 3 7 |  | 
| 4 8 | 
             
            v1.7. Deployment docs. Postgres fixes. Support association_name instead of class_name (Daniel Higginbotham). 
         | 
    
        data/DEPLOYMENT_NOTES
    CHANGED
    
    | @@ -15,12 +15,16 @@ You will <b>not</b> want to keep the generated <tt>development.conf</tt> in the | |
| 15 15 |  | 
| 16 16 | 
             
            It's easy to keep the search daemon and the indexer running in a production environment. Cronjobs are the best way:
         | 
| 17 17 |  | 
| 18 | 
            -
               | 
| 19 | 
            -
                rake ultrasphinx:index >> /log/ultrasphinx-index.log 2>&1'
         | 
| 18 | 
            +
              */6 * * * * bash -c 'cd /path/to/production/current/; RAILS_ENV=production \
         | 
| 19 | 
            +
                rake ultrasphinx:index:delta >> /log/ultrasphinx-index.log 2>&1'
         | 
| 20 | 
            +
              1 4 * * * * bash -c 'cd /path/to/production/current/; RAILS_ENV=production \
         | 
| 21 | 
            +
                rake ultrasphinx:index:main >> /log/ultrasphinx-index.log 2>&1'
         | 
| 20 22 | 
             
              */3 * * * * bash -c 'cd /path/to/production/current/; RAILS_ENV=production \
         | 
| 21 23 | 
             
                rake ultrasphinx:daemon:start >> /log/ultrasphinx-daemon.log 2>&1'
         | 
| 22 24 |  | 
| 23 | 
            -
            The first line  | 
| 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 | 
            +
             | 
| 27 | 
            +
            Of course if you don't have any models with deltas, don't include the <tt>ultrasphinx:index:delta</tt> task.
         | 
| 24 28 |  | 
| 25 29 | 
             
            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.
         | 
| 26 30 |  | 
    
        data/Manifest
    CHANGED
    
    | @@ -71,6 +71,7 @@ test/integration/app/config/environments/test.rb | |
| 71 71 | 
             
            test/integration/app/config/locomotive.yml
         | 
| 72 72 | 
             
            test/integration/app/config/routes.rb
         | 
| 73 73 | 
             
            test/integration/app/config/ultrasphinx/default.base
         | 
| 74 | 
            +
            test/integration/app/config/ultrasphinx/development.conf
         | 
| 74 75 | 
             
            test/integration/app/config/ultrasphinx/development.conf.canonical
         | 
| 75 76 | 
             
            test/integration/app/db/migrate/001_create_users.rb
         | 
| 76 77 | 
             
            test/integration/app/db/migrate/002_create_sellers.rb
         | 
| @@ -81,6 +82,7 @@ test/integration/app/db/migrate/006_add_deleted_to_user.rb | |
| 81 82 | 
             
            test/integration/app/db/migrate/007_add_lat_and_long_to_address.rb
         | 
| 82 83 | 
             
            test/integration/app/db/migrate/008_add_mission_statement_to_seller.rb
         | 
| 83 84 | 
             
            test/integration/app/db/migrate/009_create_countries.rb
         | 
| 85 | 
            +
            test/integration/app/db/schema.rb
         | 
| 84 86 | 
             
            test/integration/app/doc/README_FOR_APP
         | 
| 85 87 | 
             
            test/integration/app/public/404.html
         | 
| 86 88 | 
             
            test/integration/app/public/500.html
         | 
| @@ -123,13 +125,16 @@ test/integration/app/test/functional/states_controller_test.rb | |
| 123 125 | 
             
            test/integration/app/test/functional/users_controller_test.rb
         | 
| 124 126 | 
             
            test/integration/app/test/test_helper.rb
         | 
| 125 127 | 
             
            test/integration/app/test/unit/address_test.rb
         | 
| 128 | 
            +
            test/integration/app/test/unit/country_test.rb
         | 
| 126 129 | 
             
            test/integration/app/test/unit/seller_test.rb
         | 
| 127 130 | 
             
            test/integration/app/test/unit/state_test.rb
         | 
| 128 131 | 
             
            test/integration/app/test/unit/user_test.rb
         | 
| 129 132 | 
             
            test/integration/configure_test.rb
         | 
| 133 | 
            +
            test/integration/delta_test.rb
         | 
| 130 134 | 
             
            test/integration/search_test.rb
         | 
| 131 135 | 
             
            test/integration/server_test.rb
         | 
| 132 136 | 
             
            test/integration/spell_test.rb
         | 
| 137 | 
            +
            test/profile/benchmark.rb
         | 
| 133 138 | 
             
            test/setup.rb
         | 
| 134 139 | 
             
            test/teardown.rb
         | 
| 135 140 | 
             
            test/test_all.rb
         | 
| @@ -149,6 +154,7 @@ vendor/riddle/spec/fixtures/data/anchor.bin | |
| 149 154 | 
             
            vendor/riddle/spec/fixtures/data/any.bin
         | 
| 150 155 | 
             
            vendor/riddle/spec/fixtures/data/boolean.bin
         | 
| 151 156 | 
             
            vendor/riddle/spec/fixtures/data/distinct.bin
         | 
| 157 | 
            +
            vendor/riddle/spec/fixtures/data/field_weights.bin
         | 
| 152 158 | 
             
            vendor/riddle/spec/fixtures/data/filter.bin
         | 
| 153 159 | 
             
            vendor/riddle/spec/fixtures/data/filter_array.bin
         | 
| 154 160 | 
             
            vendor/riddle/spec/fixtures/data/filter_array_exclude.bin
         | 
| @@ -159,12 +165,16 @@ vendor/riddle/spec/fixtures/data/filter_range.bin | |
| 159 165 | 
             
            vendor/riddle/spec/fixtures/data/filter_range_exclude.bin
         | 
| 160 166 | 
             
            vendor/riddle/spec/fixtures/data/group.bin
         | 
| 161 167 | 
             
            vendor/riddle/spec/fixtures/data/index.bin
         | 
| 168 | 
            +
            vendor/riddle/spec/fixtures/data/index_weights.bin
         | 
| 162 169 | 
             
            vendor/riddle/spec/fixtures/data/phrase.bin
         | 
| 170 | 
            +
            vendor/riddle/spec/fixtures/data/rank_mode.bin
         | 
| 163 171 | 
             
            vendor/riddle/spec/fixtures/data/simple.bin
         | 
| 164 172 | 
             
            vendor/riddle/spec/fixtures/data/sort.bin
         | 
| 165 173 | 
             
            vendor/riddle/spec/fixtures/data/update_simple.bin
         | 
| 166 174 | 
             
            vendor/riddle/spec/fixtures/data/weights.bin
         | 
| 175 | 
            +
            vendor/riddle/spec/fixtures/data_generator.php
         | 
| 167 176 | 
             
            vendor/riddle/spec/fixtures/sphinx/configuration.erb
         | 
| 177 | 
            +
            vendor/riddle/spec/fixtures/sphinxapi.php
         | 
| 168 178 | 
             
            vendor/riddle/spec/fixtures/sql/conf.example.yml
         | 
| 169 179 | 
             
            vendor/riddle/spec/fixtures/sql/data.sql
         | 
| 170 180 | 
             
            vendor/riddle/spec/fixtures/sql/structure.sql
         | 
    
        data/RAKE_TASKS
    CHANGED
    
    | @@ -4,7 +4,9 @@ | |
| 4 4 | 
             
            These Rake tasks are made available to your Rails app:
         | 
| 5 5 |  | 
| 6 6 | 
             
            <tt>ultrasphinx:configure</tt>:: Rebuild the configuration file for this particular environment.
         | 
| 7 | 
            -
            <tt>ultrasphinx:index</tt>:: Reindex  | 
| 7 | 
            +
            <tt>ultrasphinx:index</tt>:: Reindex and rotate all indexes.
         | 
| 8 | 
            +
            <tt>ultrasphinx:index:delta</tt>:: Reindex and rotate the delta index.
         | 
| 9 | 
            +
            <tt>ultrasphinx:index:main</tt>:: Reindex and rotate the main index.
         | 
| 8 10 | 
             
            <tt>ultrasphinx:daemon:restart</tt>:: Restart the search daemon.
         | 
| 9 11 | 
             
            <tt>ultrasphinx:daemon:start</tt>:: Start the search daemon.
         | 
| 10 12 | 
             
            <tt>ultrasphinx:daemon:stop</tt>:: Stop the search daemon.
         | 
| @@ -12,4 +14,4 @@ These Rake tasks are made available to your Rails app: | |
| 12 14 | 
             
            <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.
         | 
| 13 15 | 
             
            <tt>ultrasphinx:bootstrap</tt>:: Bootstrap a full Sphinx environment by running configure, index, then daemon:start.
         | 
| 14 16 |  | 
| 15 | 
            -
            All tasks have shortcuts. Use <tt>us:conf</tt>, <tt>us: | 
| 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>.
         | 
    
        data/README
    CHANGED
    
    | @@ -5,7 +5,7 @@ Ruby on Rails configurator and client to the Sphinx full text search engine. | |
| 5 5 |  | 
| 6 6 | 
             
            == License
         | 
| 7 7 |  | 
| 8 | 
            -
            Copyright 2008 Cloudburst, LLC. Licensed under the AFL 3. See the included LICENSE file. Some portions copyright Pat Allan, distributed under the MIT license, and used with permission. Some portions copyright PJ Hyett and Mislav Marohnić, distributed under the MIT license, and used with permission. 
         | 
| 8 | 
            +
            Copyright 2007-2008 Cloudburst, LLC. Licensed under the AFL 3. See the included LICENSE file. Some portions copyright Pat Allan, distributed under the MIT license, and used with permission. Some portions copyright PJ Hyett and Mislav Marohnić, distributed under the MIT license, and used with permission. 
         | 
| 9 9 |  | 
| 10 10 | 
             
            The public certificate for the gem is here[http://rubyforge.org/frs/download.php/25331/evan_weaver-original-public_cert.pem]. 
         | 
| 11 11 |  | 
| @@ -14,30 +14,27 @@ If you use this software, please {make a donation}[http://blog.evanweaver.com/do | |
| 14 14 | 
             
            == Requirements
         | 
| 15 15 |  | 
| 16 16 | 
             
            * MySQL 5.0, or PostgreSQL 8.2
         | 
| 17 | 
            -
            * Sphinx 0.9.8- | 
| 17 | 
            +
            * Sphinx 0.9.8-rc1
         | 
| 18 18 | 
             
            * Rails 2.0.2
         | 
| 19 19 |  | 
| 20 20 | 
             
            More recent versions than listed are usually ok.
         | 
| 21 21 |  | 
| 22 22 | 
             
            == Features
         | 
| 23 23 |  | 
| 24 | 
            -
             | 
| 24 | 
            +
            Sphinx/Ultrasphinx is the fastest and most stable Rails fulltext search solution.
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            Features include:
         | 
| 27 | 
            +
             | 
| 25 28 | 
             
            * searching and ranking across orthogonal models
         | 
| 29 | 
            +
            * delta index support
         | 
| 26 30 | 
             
            * excerpt highlighting
         | 
| 27 | 
            -
            *  | 
| 31 | 
            +
            * Google-style query parser
         | 
| 32 | 
            +
            * spellcheck
         | 
| 28 33 | 
             
            * faceting on text, date, and numeric fields
         | 
| 29 | 
            -
             | 
| 30 | 
            -
            ActiveRecord-style SQL generation:
         | 
| 34 | 
            +
            * field weighting, merging, and aliases
         | 
| 31 35 | 
             
            * <tt>belongs_to</tt> and <tt>has_many</tt> includes
         | 
| 32 | 
            -
            *  | 
| 33 | 
            -
            *  | 
| 34 | 
            -
             | 
| 35 | 
            -
            Good Rails integration:
         | 
| 36 | 
            -
            * automatic memcached loads via <tt>cache_fu</tt>
         | 
| 37 | 
            -
            * <tt>will_paginate</tt> compatibility
         | 
| 38 | 
            -
            * query spellcheck
         | 
| 39 | 
            -
            * Google-style query parser
         | 
| 40 | 
            -
            * error recovery
         | 
| 36 | 
            +
            * drop-in compatibility with will_paginate[http://err.lighthouseapp.com/projects/466/home]
         | 
| 37 | 
            +
            * drop-in compatibility with Interlock[http://blog.evanweaver.com/files/doc/fauna/interlock/]
         | 
| 41 38 | 
             
            * multiple deployment environments
         | 
| 42 39 | 
             
            * comprehensive Rake tasks
         | 
| 43 40 |  | 
| @@ -57,7 +54,7 @@ Then, install the plugin: | |
| 57 54 |  | 
| 58 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.
         | 
| 59 56 |  | 
| 60 | 
            -
            If you need per-environment configuration, you can use <tt>RAILS_ROOT/config/ultrasphinx/development.base</tt>, etc. 
         | 
| 57 | 
            +
            If you need per-environment configuration, you can use <tt>RAILS_ROOT/config/ultrasphinx/development.base</tt>, etc. Note that ERb is also allowed within the <tt>.base</tt> files, and can be an alternative way to DRY up multiple configurations.
         | 
| 61 58 |  | 
| 62 59 | 
             
            Now, in your models, use the <tt>is_indexed</tt> method to configure a model as searchable. For example:
         | 
| 63 60 |  | 
| @@ -91,11 +88,29 @@ For more query options, including excerpt mode, see Ultrasphinx::Search. | |
| 91 88 |  | 
| 92 89 | 
             
            == Pagination
         | 
| 93 90 |  | 
| 94 | 
            -
            Once the <tt>@search</tt> object has been <tt>run</tt>, it is directly compatible with the <tt>will_paginate</tt> view helper.
         | 
| 91 | 
            +
            Once the <tt>@search</tt> object has been <tt>run</tt>, it is directly compatible with the <tt>will_paginate</tt> view helper. In your view, just do:
         | 
| 92 | 
            +
              <%= will_paginate(@search) %>
         | 
| 95 93 |  | 
| 96 94 | 
             
            == Spell checking
         | 
| 97 95 |  | 
| 98 96 | 
             
            See Ultrasphinx::Spell.
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            == Delta indexing 
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            Delta indexing speeds up your updates by not reindexing the entire dataset every time. 
         | 
| 101 | 
            +
             | 
| 102 | 
            +
            First, in your <tt>.base</tt> file, set the indexer option <tt>delta</tt> to your maximum interval between full reindexes. A day or a week is good, depending. Add a little bit to account for the time it takes the actual index to run:
         | 
| 103 | 
            +
             | 
| 104 | 
            +
              delta = <%= 1.day + 30.minutes %> 
         | 
| 105 | 
            +
             | 
| 106 | 
            +
            Now, configure your models for delta indexing in the <tt>is_indexed</tt> call:
         | 
| 107 | 
            +
             | 
| 108 | 
            +
              is_indexed :fields => ['created_at', 'title', 'body'],
         | 
| 109 | 
            +
                :delta => true
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            Now you can run <tt>rake ultrasphinx:index:delta</tt> frequently, and only records that were changed within 1 day will be reindexed. You will need to run <tt>rake ultrasphinx:index:main</tt> once a day to move the delta contents into the main index.
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            See ActiveRecord::Base .is_indexed and DEPLOYMENT_NOTES[link:files/DEPLOYMENT_NOTES.html] for more.
         | 
| 99 114 |  | 
| 100 115 | 
             
            == Available Rake tasks
         | 
| 101 116 |  | 
| @@ -105,7 +120,9 @@ See RAKE_TASKS[link:files/RAKE_TASKS.html]. | |
| 105 120 |  | 
| 106 121 | 
             
            See DEPLOYMENT_NOTES[link:files/DEPLOYMENT_NOTES.html].
         | 
| 107 122 |  | 
| 108 | 
            -
            ==  | 
| 123 | 
            +
            == Gotchas
         | 
| 124 | 
            +
             | 
| 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>.
         | 
| 109 126 |  | 
| 110 127 | 
             
            PostgreSQL 8.2 and higher are well supported. However, make sure you have executed <tt>CREATE LANGUAGE plpgsql;</tt> at least once. This step does not need to be repeated, so depending on your DB permissions, you might be able to put it in a migration.
         | 
| 111 128 |  | 
    
        data/TODO
    CHANGED
    
    
    
        data/examples/default.base
    CHANGED
    
    | @@ -3,8 +3,8 @@ | |
| 3 3 | 
             
            # Sphinx/Ultrasphinx user-configurable options.
         | 
| 4 4 | 
             
            #
         | 
| 5 5 | 
             
            # Copy this file to RAILS_ROOT/config/ultrasphinx. You can use individual 
         | 
| 6 | 
            -
            # namespaces if you want (e.g. development.base, production.base,
         | 
| 7 | 
            -
            # test.base).
         | 
| 6 | 
            +
            # namespaces if you want (e.g. development.base, production.base, 
         | 
| 7 | 
            +
            # test.base). Note that ERb is also allowed.
         | 
| 8 8 | 
             
            #
         | 
| 9 9 | 
             
            # This file should not be handed directly to Sphinx. Use the rake task 
         | 
| 10 10 | 
             
            #
         | 
| @@ -15,56 +15,61 @@ | |
| 15 15 | 
             
            # to Sphinx.
         | 
| 16 16 | 
             
            # 
         | 
| 17 17 | 
             
            # It is safe to edit .base files by hand. It is not safe to edit the generated 
         | 
| 18 | 
            -
            # .conf files. Do not symlink the .conf file to the .base file | 
| 19 | 
            -
            # people think they need to do that. It's wrong.
         | 
| 18 | 
            +
            # .conf files. Do not symlink the .conf file to the .base file; it's wrong.
         | 
| 20 19 | 
             
            #
         | 
| 21 20 |  | 
| 21 | 
            +
            <% path = "/opt/local/var/db/sphinx/" %>
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            # Indexing options
         | 
| 22 24 | 
             
            indexer
         | 
| 23 | 
            -
            {
         | 
| 24 | 
            -
              # Indexer running options
         | 
| 25 | 
            +
            {  
         | 
| 25 26 | 
             
              mem_limit = 256M 
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              # Ultrasphinx-specific key
         | 
| 29 | 
            +
              delta = <%= 1.day + 30.minutes %> 
         | 
| 26 30 | 
             
            }
         | 
| 27 31 |  | 
| 32 | 
            +
            # Daemon options
         | 
| 28 33 | 
             
            searchd
         | 
| 29 | 
            -
            {
         | 
| 30 | 
            -
              # Daemon options
         | 
| 34 | 
            +
            {  
         | 
| 31 35 | 
             
              # What interface the search daemon should listen on and where to store its logs
         | 
| 32 36 | 
             
              address = 0.0.0.0
         | 
| 33 37 | 
             
              port = 3312
         | 
| 34 38 | 
             
              seamless_rotate = 1
         | 
| 35 | 
            -
              log =  | 
| 36 | 
            -
              query_log =  | 
| 39 | 
            +
              log = <%= path %>log/searchd.log
         | 
| 40 | 
            +
              query_log = <%= path %>log/query.log
         | 
| 37 41 | 
             
              read_timeout = 5
         | 
| 38 42 | 
             
              max_children = 300
         | 
| 39 | 
            -
              pid_file =  | 
| 43 | 
            +
              pid_file = <%= path %>log/searchd.pid
         | 
| 40 44 | 
             
              max_matches = 100000
         | 
| 41 45 | 
             
            }
         | 
| 42 46 |  | 
| 47 | 
            +
            # Client options
         | 
| 43 48 | 
             
            client
         | 
| 44 49 | 
             
            {
         | 
| 45 | 
            -
              # Client options
         | 
| 46 50 | 
             
              # Name of the Aspell dictionary (two letters max)
         | 
| 47 51 | 
             
              dictionary_name = ap
         | 
| 52 | 
            +
              
         | 
| 48 53 | 
             
              # How your application connects to the search daemon (not necessarily the same as above)
         | 
| 49 54 | 
             
              server_host = localhost
         | 
| 50 55 | 
             
              server_port = 3312
         | 
| 51 56 | 
             
            }
         | 
| 52 57 |  | 
| 58 | 
            +
            # Individual SQL source options
         | 
| 53 59 | 
             
            source
         | 
| 54 | 
            -
            {
         | 
| 55 | 
            -
              # Individual SQL source options
         | 
| 60 | 
            +
            {  
         | 
| 56 61 | 
             
              sql_ranged_throttle = 0  
         | 
| 57 62 | 
             
              sql_range_step = 5000   
         | 
| 58 63 | 
             
              sql_query_post =
         | 
| 59 64 | 
             
            }
         | 
| 60 65 |  | 
| 66 | 
            +
            # Index building options
         | 
| 61 67 | 
             
            index
         | 
| 62 | 
            -
            {
         | 
| 63 | 
            -
               | 
| 64 | 
            -
               | 
| 65 | 
            -
              docinfo = extern # just leave this alone
         | 
| 68 | 
            +
            {  
         | 
| 69 | 
            +
              path = <%= path %>
         | 
| 70 | 
            +
              docinfo = extern # Just leave this alone
         | 
| 66 71 | 
             
              morphology = stem_en
         | 
| 67 | 
            -
              stopwords = #  | 
| 72 | 
            +
              stopwords = # <%= path %>/ap-stopwords.txt
         | 
| 68 73 | 
             
              min_word_len = 1
         | 
| 69 74 |  | 
| 70 75 | 
             
              # HTML-specific options
         | 
    
        data/lib/ultrasphinx.rb
    CHANGED
    
    | @@ -17,7 +17,7 @@ require 'ultrasphinx/associations' | |
| 17 17 | 
             
            require 'ultrasphinx/core_extensions'
         | 
| 18 18 | 
             
            require 'ultrasphinx/is_indexed'
         | 
| 19 19 |  | 
| 20 | 
            -
            if (ActiveRecord::Base.connection rescue nil) # XXX  | 
| 20 | 
            +
            if (ActiveRecord::Base.connection rescue nil) # XXX Not sure why this needed to be wrapped.
         | 
| 21 21 | 
             
              require 'ultrasphinx/configure'
         | 
| 22 22 | 
             
              require 'ultrasphinx/autoload'
         | 
| 23 23 | 
             
              require 'ultrasphinx/fields'
         | 
| @@ -12,7 +12,7 @@ module Ultrasphinx | |
| 12 12 | 
             
                      Dir["**/*.rb"].each do |filename|
         | 
| 13 13 | 
             
                        open(filename) do |file| 
         | 
| 14 14 | 
             
                          begin
         | 
| 15 | 
            -
                            if file.grep( | 
| 15 | 
            +
                            if file.grep(/^\s+is_indexed/).any?
         | 
| 16 16 | 
             
                              filename = filename[0..-4]
         | 
| 17 17 | 
             
                              begin                
         | 
| 18 18 | 
             
                                File.basename(filename).camelize.constantize
         | 
| @@ -41,21 +41,33 @@ module Ultrasphinx | |
| 41 41 |  | 
| 42 42 | 
             
                    say "rebuilding configurations for #{RAILS_ENV} environment" 
         | 
| 43 43 | 
             
                    say "available models are #{MODEL_CONFIGURATION.keys.to_sentence}"
         | 
| 44 | 
            -
                    File.open(CONF_PATH, "w") do |conf|
         | 
| 45 | 
            -
                    
         | 
| 44 | 
            +
                    File.open(CONF_PATH, "w") do |conf|              
         | 
| 46 45 | 
             
                      conf.puts global_header            
         | 
| 47 | 
            -
                       | 
| 48 | 
            -
             | 
| 49 | 
            -
                       | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
                         | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 46 | 
            +
                      say "generating SQL"    
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                      INDEXES.each do |index|
         | 
| 49 | 
            +
                        sources = []
         | 
| 50 | 
            +
                        cached_groups = Fields.instance.groups.join("\n")
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                        MODEL_CONFIGURATION.each_with_index do |model_and_options, class_id|              
         | 
| 53 | 
            +
                          # This relies on hash sort order being deterministic per-machine
         | 
| 54 | 
            +
                          model, options = model_and_options
         | 
| 55 | 
            +
                          klass = model.constantize
         | 
| 56 | 
            +
                          source = "#{model.tableize.gsub('/', '__')}_#{index}"
         | 
| 57 | 
            +
             
         | 
| 58 | 
            +
                          if index != DELTA_INDEX or options['delta']
         | 
| 59 | 
            +
                            # If we are building the delta, we only want to include the models that requested it
         | 
| 60 | 
            +
                            conf.puts build_source(index, Fields.instance, model, options, class_id, klass, source, cached_groups)
         | 
| 61 | 
            +
                            sources << source                
         | 
| 62 | 
            +
                          end
         | 
| 63 | 
            +
                        end
         | 
| 64 | 
            +
                        
         | 
| 65 | 
            +
                        if sources.any?
         | 
| 66 | 
            +
                          # Don't generate a delta index if there are no delta tables
         | 
| 67 | 
            +
                          conf.puts build_index(index, sources)
         | 
| 68 | 
            +
                        end
         | 
| 69 | 
            +
                        
         | 
| 56 70 | 
             
                      end
         | 
| 57 | 
            -
                      
         | 
| 58 | 
            -
                      conf.puts build_index(sources)
         | 
| 59 71 | 
             
                    end              
         | 
| 60 72 | 
             
                  end
         | 
| 61 73 |  | 
| @@ -68,7 +80,8 @@ module Ultrasphinx | |
| 68 80 | 
             
                    ["\n# Auto-generated at #{Time.now}.",
         | 
| 69 81 | 
             
                     "# Hand modifications will be overwritten.",
         | 
| 70 82 | 
             
                     "# #{BASE_PATH}\n",
         | 
| 71 | 
            -
                     INDEXER_SETTINGS._to_conf_string('indexer'),
         | 
| 83 | 
            +
                     INDEXER_SETTINGS.except('delta')._to_conf_string('indexer'),
         | 
| 84 | 
            +
                     "",
         | 
| 72 85 | 
             
                     DAEMON_SETTINGS._to_conf_string("searchd")]
         | 
| 73 86 | 
             
                  end      
         | 
| 74 87 |  | 
| @@ -86,9 +99,31 @@ module Ultrasphinx | |
| 86 99 | 
             
                    end                 
         | 
| 87 100 | 
             
                    conf.sort.join("\n")
         | 
| 88 101 | 
             
                  end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                  
         | 
| 104 | 
            +
                  def build_delta_condition(index, klass, options)
         | 
| 105 | 
            +
                    if index == DELTA_INDEX and options['delta']
         | 
| 106 | 
            +
                      # Add delta condition if necessary
         | 
| 107 | 
            +
                      table, field = klass.table_name, options['delta']['field']
         | 
| 108 | 
            +
                      source_string = "#{table}.#{field}"
         | 
| 109 | 
            +
                      delta_column = klass.columns_hash[field] 
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                      if delta_column 
         | 
| 112 | 
            +
                        raise ConfigurationError, "#{source_string} is not a :datetime" unless delta_column.type == :datetime
         | 
| 113 | 
            +
                        if (options['fields'] + options['concatenate'] + options['include']).detect { |entry| entry['sortable'] }
         | 
| 114 | 
            +
                          # Warning about the sortable problem
         | 
| 115 | 
            +
                          # XXX Kind of in an odd place, but I want to happen at index time
         | 
| 116 | 
            +
                          Ultrasphinx.say "warning; text sortable columns on #{klass.name} will return wrong results with partial delta indexing"
         | 
| 117 | 
            +
                        end            
         | 
| 118 | 
            +
                        string = "#{source_string} > #{SQL_FUNCTIONS[ADAPTER]['delta']._interpolate(INDEXER_SETTINGS['delta'])}";
         | 
| 119 | 
            +
                      else
         | 
| 120 | 
            +
                        Ultrasphinx.say "warning; #{klass.name} will reindex the entire table during delta indexing"
         | 
| 121 | 
            +
                      end
         | 
| 122 | 
            +
                    end
         | 
| 123 | 
            +
                  end
         | 
| 89 124 |  | 
| 90 125 |  | 
| 91 | 
            -
                  def setup_source_arrays(klass, fields, class_id, conditions)        
         | 
| 126 | 
            +
                  def setup_source_arrays(index, klass, fields, class_id, conditions)        
         | 
| 92 127 | 
             
                    condition_strings = Array(conditions).map do |condition| 
         | 
| 93 128 | 
             
                      "(#{condition})"
         | 
| 94 129 | 
             
                    end
         | 
| @@ -101,12 +136,13 @@ module Ultrasphinx | |
| 101 136 | 
             
                  end
         | 
| 102 137 |  | 
| 103 138 |  | 
| 104 | 
            -
                  def range_select_string(klass)
         | 
| 139 | 
            +
                  def range_select_string(klass, delta_condition)
         | 
| 105 140 | 
             
                    ["sql_query_range = SELECT",
         | 
| 106 141 | 
             
                      SQL_FUNCTIONS[ADAPTER]['range_cast']._interpolate("MIN(#{klass.primary_key})"),
         | 
| 107 | 
            -
                      ", | 
| 142 | 
            +
                      ",",
         | 
| 108 143 | 
             
                      SQL_FUNCTIONS[ADAPTER]['range_cast']._interpolate("MAX(#{klass.primary_key})"),
         | 
| 109 | 
            -
                      "FROM #{klass.table_name}"
         | 
| 144 | 
            +
                      "FROM #{klass.table_name}",
         | 
| 145 | 
            +
                      ("WHERE #{delta_condition}" if delta_condition),
         | 
| 110 146 | 
             
                    ].join(" ")
         | 
| 111 147 | 
             
                  end
         | 
| 112 148 |  | 
| @@ -116,11 +152,16 @@ module Ultrasphinx | |
| 116 152 | 
             
                  end      
         | 
| 117 153 |  | 
| 118 154 |  | 
| 119 | 
            -
                  def build_source(fields, model, options, class_id, klass, source, groups)
         | 
| 155 | 
            +
                  def build_source(index, fields, model, options, class_id, klass, source, groups)
         | 
| 120 156 |  | 
| 121 157 | 
             
                    column_strings, join_strings, condition_strings, group_bys, use_distinct, remaining_columns = 
         | 
| 122 158 | 
             
                      setup_source_arrays(
         | 
| 123 | 
            -
                        klass, fields, class_id, options['conditions'])
         | 
| 159 | 
            +
                        index, klass, fields, class_id, options['conditions'])
         | 
| 160 | 
            +
                        
         | 
| 161 | 
            +
                    delta_condition = 
         | 
| 162 | 
            +
                      build_delta_condition(
         | 
| 163 | 
            +
                        index, klass, options)             
         | 
| 164 | 
            +
                    condition_strings << delta_condition if delta_condition
         | 
| 124 165 |  | 
| 125 166 | 
             
                    column_strings, join_strings, group_bys, remaining_columns = 
         | 
| 126 167 | 
             
                      build_regular_fields(
         | 
| @@ -140,7 +181,7 @@ module Ultrasphinx | |
| 140 181 | 
             
                     "source #{source}\n{",
         | 
| 141 182 | 
             
                      SOURCE_SETTINGS._to_conf_string,
         | 
| 142 183 | 
             
                      setup_source_database(klass),
         | 
| 143 | 
            -
                      range_select_string(klass),
         | 
| 184 | 
            +
                      range_select_string(klass, delta_condition),
         | 
| 144 185 | 
             
                      build_query(klass, column_strings, join_strings, condition_strings, use_distinct, group_bys),
         | 
| 145 186 | 
             
                      "\n" + groups,
         | 
| 146 187 | 
             
                      query_info_string(klass, class_id),
         | 
| @@ -271,13 +312,13 @@ module Ultrasphinx | |
| 271 312 | 
             
                  end
         | 
| 272 313 |  | 
| 273 314 |  | 
| 274 | 
            -
                  def build_index(sources)
         | 
| 315 | 
            +
                  def build_index(index, sources)
         | 
| 275 316 | 
             
                    ["\n# Index configuration\n\n",
         | 
| 276 | 
            -
                      "index #{ | 
| 317 | 
            +
                      "index #{index}\n{",
         | 
| 277 318 | 
             
                      sources.sort.map do |source| 
         | 
| 278 319 | 
             
                        "  source = #{source}"
         | 
| 279 320 | 
             
                      end.join("\n"),          
         | 
| 280 | 
            -
                      INDEX_SETTINGS.merge('path' => INDEX_SETTINGS['path'] + "/sphinx_index_#{ | 
| 321 | 
            +
                      INDEX_SETTINGS.merge('path' => INDEX_SETTINGS['path'] + "/sphinx_index_#{index}")._to_conf_string,
         | 
| 281 322 | 
             
                     "}\n\n"]
         | 
| 282 323 | 
             
                  end
         | 
| 283 324 |  |