searchkick 1.2.1 → 1.3.0
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.
- checksums.yaml +4 -4
 - data/.gitignore +2 -0
 - data/.travis.yml +17 -5
 - data/CHANGELOG.md +6 -0
 - data/LICENSE.txt +1 -1
 - data/README.md +26 -12
 - data/lib/searchkick.rb +4 -0
 - data/lib/searchkick/index.rb +62 -29
 - data/lib/searchkick/model.rb +3 -1
 - data/lib/searchkick/query.rb +334 -258
 - data/lib/searchkick/version.rb +1 -1
 - data/test/aggs_test.rb +4 -0
 - data/test/ci/before_install.sh +6 -2
 - data/test/facets_test.rb +1 -1
 - data/test/gemfiles/apartment.gemfile +8 -0
 - data/test/match_test.rb +8 -0
 - data/test/multi_tenancy_test.rb +22 -0
 - data/test/order_test.rb +6 -0
 - data/test/sql_test.rb +5 -0
 - data/test/test_helper.rb +48 -3
 - metadata +7 -3
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 9328dde4ac72c1fb914fdcbffe6a544e6f64b335
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: e59db37c34cc78f48139a8f6d604d2c4eb108d06
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 181ac8dc2d783231b7696094583312ca73e4b1104f7a91af76cde94f30ffcd6c4d89bd88ace568fcf1825776ae348c8bb2c1e7b50061407251d6805fcf45281a
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 786f655864dbdc1f9d978779000b6ae762be9ea476f832515cba1b46fa923c9dee8174bc92dff247580fdabc10a4d8aa4aaacb2690c0eea9d3fb3881e96e8d55
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.travis.yml
    CHANGED
    
    | 
         @@ -5,7 +5,7 @@ services: 
     | 
|
| 
       5 
5 
     | 
    
         
             
              - mongodb
         
     | 
| 
       6 
6 
     | 
    
         
             
            before_install:
         
     | 
| 
       7 
7 
     | 
    
         
             
              - ./test/ci/before_install.sh
         
     | 
| 
       8 
     | 
    
         
            -
            script: bundle exec rake test
         
     | 
| 
      
 8 
     | 
    
         
            +
            script: RUBYOPT=W0 bundle exec rake test
         
     | 
| 
       9 
9 
     | 
    
         
             
            before_script:
         
     | 
| 
       10 
10 
     | 
    
         
             
              - psql -c 'create database searchkick_test;' -U postgres
         
     | 
| 
       11 
11 
     | 
    
         
             
            notifications:
         
     | 
| 
         @@ -22,10 +22,22 @@ gemfile: 
     | 
|
| 
       22 
22 
     | 
    
         
             
              - test/gemfiles/mongoid3.gemfile
         
     | 
| 
       23 
23 
     | 
    
         
             
              - test/gemfiles/mongoid4.gemfile
         
     | 
| 
       24 
24 
     | 
    
         
             
              - test/gemfiles/mongoid5.gemfile
         
     | 
| 
      
 25 
     | 
    
         
            +
            env:
         
     | 
| 
      
 26 
     | 
    
         
            +
              - ELASTICSEARCH_VERSION=2.3.0
         
     | 
| 
       25 
27 
     | 
    
         
             
            matrix:
         
     | 
| 
       26 
28 
     | 
    
         
             
              include:
         
     | 
| 
       27 
     | 
    
         
            -
                - gemfile:  
     | 
| 
       28 
     | 
    
         
            -
                  env:  
     | 
| 
      
 29 
     | 
    
         
            +
                - gemfile: Gemfile
         
     | 
| 
      
 30 
     | 
    
         
            +
                  env: ELASTICSEARCH_VERSION=1.0.0
         
     | 
| 
      
 31 
     | 
    
         
            +
                - gemfile: Gemfile
         
     | 
| 
      
 32 
     | 
    
         
            +
                  env: ELASTICSEARCH_VERSION=1.7.0
         
     | 
| 
      
 33 
     | 
    
         
            +
                - gemfile: Gemfile
         
     | 
| 
      
 34 
     | 
    
         
            +
                  env: ELASTICSEARCH_VERSION=2.0.0
         
     | 
| 
      
 35 
     | 
    
         
            +
                - gemfile: Gemfile
         
     | 
| 
      
 36 
     | 
    
         
            +
                  env: ELASTICSEARCH_VERSION=5.0.0-alpha2
         
     | 
| 
      
 37 
     | 
    
         
            +
                # - gemfile: test/gemfiles/nobrainer.gemfile
         
     | 
| 
      
 38 
     | 
    
         
            +
                #   env: NOBRAINER=true
         
     | 
| 
       29 
39 
     | 
    
         
             
              allow_failures:
         
     | 
| 
       30 
     | 
    
         
            -
                - gemfile:  
     | 
| 
       31 
     | 
    
         
            -
                  env:  
     | 
| 
      
 40 
     | 
    
         
            +
                - gemfile: Gemfile
         
     | 
| 
      
 41 
     | 
    
         
            +
                  env: ELASTICSEARCH_VERSION=5.0.0-alpha2
         
     | 
| 
      
 42 
     | 
    
         
            +
                # - gemfile: test/gemfiles/nobrainer.gemfile
         
     | 
| 
      
 43 
     | 
    
         
            +
                #   env: NOBRAINER=true
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    
    
        data/LICENSE.txt
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | 
         @@ -21,8 +21,6 @@ Plus: 
     | 
|
| 
       21 
21 
     | 
    
         
             
            - “Did you mean” suggestions
         
     | 
| 
       22 
22 
     | 
    
         
             
            - works with ActiveRecord, Mongoid, and NoBrainer
         
     | 
| 
       23 
23 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
            **Searchkick 1.0 was just released!** See [instructions for upgrading](#100)
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
24 
     | 
    
         
             
            :speech_balloon: Get [handcrafted updates](http://chartkick.us7.list-manage.com/subscribe?u=952c861f99eb43084e0a49f98&id=6ea6541e8e&group[0][4]=true) for new features
         
     | 
| 
       27 
25 
     | 
    
         | 
| 
       28 
26 
     | 
    
         
             
            :tangerine: Battle-tested at [Instacart](https://www.instacart.com/opensource)
         
     | 
| 
         @@ -247,6 +245,12 @@ Available options are: 
     | 
|
| 
       247 
245 
     | 
    
         
             
            User.search params[:q], fields: [{email: :exact}, :name]
         
     | 
| 
       248 
246 
     | 
    
         
             
            ```
         
     | 
| 
       249 
247 
     | 
    
         | 
| 
      
 248 
     | 
    
         
            +
            ### Phrase Matches
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 251 
     | 
    
         
            +
            User.search "fresh honey", match: :phrase
         
     | 
| 
      
 252 
     | 
    
         
            +
            ```
         
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
       250 
254 
     | 
    
         
             
            ### Language
         
     | 
| 
       251 
255 
     | 
    
         | 
| 
       252 
256 
     | 
    
         
             
            Searchkick defaults to English for stemming.  To change this, use:
         
     | 
| 
         @@ -329,7 +333,7 @@ gem 'gemoji-parser' 
     | 
|
| 
       329 
333 
     | 
    
         
             
            And use:
         
     | 
| 
       330 
334 
     | 
    
         | 
| 
       331 
335 
     | 
    
         
             
            ```ruby
         
     | 
| 
       332 
     | 
    
         
            -
            Product.search " 
     | 
| 
      
 336 
     | 
    
         
            +
            Product.search "🍨🍰", emoji: true
         
     | 
| 
       333 
337 
     | 
    
         
             
            ```
         
     | 
| 
       334 
338 
     | 
    
         | 
| 
       335 
339 
     | 
    
         
             
            ### Indexing
         
     | 
| 
         @@ -633,6 +637,12 @@ price_ranges = [{to: 20}, {from: 20, to: 50}, {from: 50}] 
     | 
|
| 
       633 
637 
     | 
    
         
             
            Product.search "*", aggs: {price: {ranges: price_ranges}}
         
     | 
| 
       634 
638 
     | 
    
         
             
            ```
         
     | 
| 
       635 
639 
     | 
    
         | 
| 
      
 640 
     | 
    
         
            +
            Minimum document count
         
     | 
| 
      
 641 
     | 
    
         
            +
             
     | 
| 
      
 642 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 643 
     | 
    
         
            +
            Product.search "apples", aggs: {store_id: {min_doc_count: 2}}
         
     | 
| 
      
 644 
     | 
    
         
            +
            ```
         
     | 
| 
      
 645 
     | 
    
         
            +
             
     | 
| 
       636 
646 
     | 
    
         
             
            #### Moving From Facets
         
     | 
| 
       637 
647 
     | 
    
         | 
| 
       638 
648 
     | 
    
         
             
            1. Replace `facets` with `aggs` in searches. **Note:** Stats facets are not supported at this time.
         
     | 
| 
         @@ -838,7 +848,7 @@ Searchkick supports [Elasticsearch’s routing feature](https://www.elastic.co/b 
     | 
|
| 
       838 
848 
     | 
    
         
             
            class Business < ActiveRecord::Base
         
     | 
| 
       839 
849 
     | 
    
         
             
              searchkick routing: true
         
     | 
| 
       840 
850 
     | 
    
         | 
| 
       841 
     | 
    
         
            -
              def  
     | 
| 
      
 851 
     | 
    
         
            +
              def search_routing
         
     | 
| 
       842 
852 
     | 
    
         
             
                city_id
         
     | 
| 
       843 
853 
     | 
    
         
             
              end
         
     | 
| 
       844 
854 
     | 
    
         
             
            end
         
     | 
| 
         @@ -919,20 +929,20 @@ Searchkick uses `ENV["ELASTICSEARCH_URL"]` for the Elasticsearch server.  This d 
     | 
|
| 
       919 
929 
     | 
    
         | 
| 
       920 
930 
     | 
    
         
             
            ### Heroku
         
     | 
| 
       921 
931 
     | 
    
         | 
| 
       922 
     | 
    
         
            -
            Choose an add-on: [SearchBox](https://elements.heroku.com/addons/searchbox), [Bonsai](https://elements.heroku.com/addons/bonsai), or [ 
     | 
| 
      
 932 
     | 
    
         
            +
            Choose an add-on: [SearchBox](https://elements.heroku.com/addons/searchbox), [Bonsai](https://elements.heroku.com/addons/bonsai), or [Elastic Cloud](https://elements.heroku.com/addons/foundelasticsearch).
         
     | 
| 
       923 
933 
     | 
    
         | 
| 
       924 
934 
     | 
    
         
             
            ```sh
         
     | 
| 
       925 
935 
     | 
    
         
             
            # SearchBox
         
     | 
| 
       926 
     | 
    
         
            -
            heroku addons: 
     | 
| 
       927 
     | 
    
         
            -
            heroku config: 
     | 
| 
      
 936 
     | 
    
         
            +
            heroku addons:create searchbox:starter
         
     | 
| 
      
 937 
     | 
    
         
            +
            heroku config:set ELASTICSEARCH_URL=`heroku config:get SEARCHBOX_URL`
         
     | 
| 
       928 
938 
     | 
    
         | 
| 
       929 
939 
     | 
    
         
             
            # Bonsai
         
     | 
| 
       930 
     | 
    
         
            -
            heroku addons: 
     | 
| 
       931 
     | 
    
         
            -
            heroku config: 
     | 
| 
      
 940 
     | 
    
         
            +
            heroku addons:create bonsai
         
     | 
| 
      
 941 
     | 
    
         
            +
            heroku config:set ELASTICSEARCH_URL=`heroku config:get BONSAI_URL`
         
     | 
| 
       932 
942 
     | 
    
         | 
| 
       933 
943 
     | 
    
         
             
            # Found
         
     | 
| 
       934 
     | 
    
         
            -
            heroku addons: 
     | 
| 
       935 
     | 
    
         
            -
            heroku config: 
     | 
| 
      
 944 
     | 
    
         
            +
            heroku addons:create foundelasticsearch
         
     | 
| 
      
 945 
     | 
    
         
            +
            heroku config:set ELASTICSEARCH_URL=`heroku config:get FOUNDELASTICSEARCH_URL`
         
     | 
| 
       936 
946 
     | 
    
         
             
            ```
         
     | 
| 
       937 
947 
     | 
    
         | 
| 
       938 
948 
     | 
    
         
             
            Then deploy and reindex:
         
     | 
| 
         @@ -1104,7 +1114,7 @@ Searchkick.multi_search([fresh_products, frozen_products]) 
     | 
|
| 
       1104 
1114 
     | 
    
         | 
| 
       1105 
1115 
     | 
    
         
             
            Then use `fresh_products` and `frozen_products` as typical results.
         
     | 
| 
       1106 
1116 
     | 
    
         | 
| 
       1107 
     | 
    
         
            -
            **Note:** Errors are not raised as with single requests. Use the `error` method on each query to check for errors. Also, the `below` option for misspellings  
     | 
| 
      
 1117 
     | 
    
         
            +
            **Note:** Errors are not raised as with single requests. Use the `error` method on each query to check for errors. Also, if you use the `below` option for misspellings, misspellings will be disabled.
         
     | 
| 
       1108 
1118 
     | 
    
         | 
| 
       1109 
1119 
     | 
    
         
             
            ## Reference
         
     | 
| 
       1110 
1120 
     | 
    
         | 
| 
         @@ -1316,6 +1326,10 @@ product.reindex # don't forget this 
     | 
|
| 
       1316 
1326 
     | 
    
         
             
            Product.searchkick_index.refresh # or this
         
     | 
| 
       1317 
1327 
     | 
    
         
             
            ```
         
     | 
| 
       1318 
1328 
     | 
    
         | 
| 
      
 1329 
     | 
    
         
            +
            ## Multi-Tenancy
         
     | 
| 
      
 1330 
     | 
    
         
            +
             
     | 
| 
      
 1331 
     | 
    
         
            +
            Check out [this great post](https://www.tiagoamaro.com.br/2014/12/11/multi-tenancy-with-searchkick/) on the [Apartment](https://github.com/influitive/apartment) gem. Follow a similar pattern if you use another gem.
         
     | 
| 
      
 1332 
     | 
    
         
            +
             
     | 
| 
       1319 
1333 
     | 
    
         
             
            ## Migrating from Tire
         
     | 
| 
       1320 
1334 
     | 
    
         | 
| 
       1321 
1335 
     | 
    
         
             
            1. Change `search` methods to `tire.search` and add index name in existing search calls
         
     | 
    
        data/lib/searchkick.rb
    CHANGED
    
    | 
         @@ -58,6 +58,10 @@ module Searchkick 
     | 
|
| 
       58 
58 
     | 
    
         
             
                @server_version ||= client.info["version"]["number"]
         
     | 
| 
       59 
59 
     | 
    
         
             
              end
         
     | 
| 
       60 
60 
     | 
    
         | 
| 
      
 61 
     | 
    
         
            +
              def self.server_below?(version)
         
     | 
| 
      
 62 
     | 
    
         
            +
                Gem::Version.new(server_version) < Gem::Version.new(version)
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
       61 
65 
     | 
    
         
             
              def self.enable_callbacks
         
     | 
| 
       62 
66 
     | 
    
         
             
                self.callbacks_value = nil
         
     | 
| 
       63 
67 
     | 
    
         
             
              end
         
     | 
    
        data/lib/searchkick/index.rb
    CHANGED
    
    | 
         @@ -36,7 +36,7 @@ module Searchkick 
     | 
|
| 
       36 
36 
     | 
    
         
             
                    begin
         
     | 
| 
       37 
37 
     | 
    
         
             
                      client.indices.get_alias(name: name).keys
         
     | 
| 
       38 
38 
     | 
    
         
             
                    rescue Elasticsearch::Transport::Transport::Errors::NotFound
         
     | 
| 
       39 
     | 
    
         
            -
                       
     | 
| 
      
 39 
     | 
    
         
            +
                      {}
         
     | 
| 
       40 
40 
     | 
    
         
             
                    end
         
     | 
| 
       41 
41 
     | 
    
         
             
                  actions = old_indices.map { |old_name| {remove: {index: old_name, alias: name}} } + [{add: {index: new_name, alias: name}}]
         
     | 
| 
       42 
42 
     | 
    
         
             
                  client.indices.update_aliases body: {actions: actions}
         
     | 
| 
         @@ -146,7 +146,7 @@ module Searchkick 
     | 
|
| 
       146 
146 
     | 
    
         
             
                    begin
         
     | 
| 
       147 
147 
     | 
    
         
             
                      client.indices.get_aliases
         
     | 
| 
       148 
148 
     | 
    
         
             
                    rescue Elasticsearch::Transport::Transport::Errors::NotFound
         
     | 
| 
       149 
     | 
    
         
            -
                       
     | 
| 
      
 149 
     | 
    
         
            +
                      {}
         
     | 
| 
       150 
150 
     | 
    
         
             
                    end
         
     | 
| 
       151 
151 
     | 
    
         
             
                  indices = all_indices.select { |k, v| (v.empty? || v["aliases"].empty?) && k =~ /\A#{Regexp.escape(name)}_\d{14,17}\z/ }.keys
         
     | 
| 
       152 
152 
     | 
    
         
             
                  indices.each do |index|
         
     | 
| 
         @@ -218,6 +218,22 @@ module Searchkick 
     | 
|
| 
       218 
218 
     | 
    
         
             
                    settings = options[:settings] || {}
         
     | 
| 
       219 
219 
     | 
    
         
             
                    mappings = options[:mappings]
         
     | 
| 
       220 
220 
     | 
    
         
             
                  else
         
     | 
| 
      
 221 
     | 
    
         
            +
                    below22 = Searchkick.server_below?("2.2.0")
         
     | 
| 
      
 222 
     | 
    
         
            +
                    below50 = Searchkick.server_below?("5.0.0-alpha1")
         
     | 
| 
      
 223 
     | 
    
         
            +
                    default_type = below50 ? "string" : "text"
         
     | 
| 
      
 224 
     | 
    
         
            +
                    default_analyzer = below50 ? :default_index : :default
         
     | 
| 
      
 225 
     | 
    
         
            +
                    keyword_mapping =
         
     | 
| 
      
 226 
     | 
    
         
            +
                      if below50
         
     | 
| 
      
 227 
     | 
    
         
            +
                        {
         
     | 
| 
      
 228 
     | 
    
         
            +
                          type: default_type,
         
     | 
| 
      
 229 
     | 
    
         
            +
                          index: "not_analyzed"
         
     | 
| 
      
 230 
     | 
    
         
            +
                        }
         
     | 
| 
      
 231 
     | 
    
         
            +
                      else
         
     | 
| 
      
 232 
     | 
    
         
            +
                        {
         
     | 
| 
      
 233 
     | 
    
         
            +
                          type: "keyword"
         
     | 
| 
      
 234 
     | 
    
         
            +
                        }
         
     | 
| 
      
 235 
     | 
    
         
            +
                      end
         
     | 
| 
      
 236 
     | 
    
         
            +
             
     | 
| 
       221 
237 
     | 
    
         
             
                    settings = {
         
     | 
| 
       222 
238 
     | 
    
         
             
                      analysis: {
         
     | 
| 
       223 
239 
     | 
    
         
             
                        analyzer: {
         
     | 
| 
         @@ -226,7 +242,7 @@ module Searchkick 
     | 
|
| 
       226 
242 
     | 
    
         
             
                            tokenizer: "keyword",
         
     | 
| 
       227 
243 
     | 
    
         
             
                            filter: ["lowercase"] + (options[:stem_conversions] == false ? [] : ["searchkick_stemmer"])
         
     | 
| 
       228 
244 
     | 
    
         
             
                          },
         
     | 
| 
       229 
     | 
    
         
            -
                           
     | 
| 
      
 245 
     | 
    
         
            +
                          default_analyzer => {
         
     | 
| 
       230 
246 
     | 
    
         
             
                            type: "custom",
         
     | 
| 
       231 
247 
     | 
    
         
             
                            # character filters -> tokenizer -> token filters
         
     | 
| 
       232 
248 
     | 
    
         
             
                            # https://www.elastic.co/guide/en/elasticsearch/guide/current/analysis-intro.html
         
     | 
| 
         @@ -380,8 +396,8 @@ module Searchkick 
     | 
|
| 
       380 
396 
     | 
    
         
             
                      # - Only apply the synonym expansion at index time
         
     | 
| 
       381 
397 
     | 
    
         
             
                      # - Don't have the synonym filter applied search
         
     | 
| 
       382 
398 
     | 
    
         
             
                      # - Use directional synonyms where appropriate. You want to make sure that you're not injecting terms that are too general.
         
     | 
| 
       383 
     | 
    
         
            -
                      settings[:analysis][:analyzer][ 
     | 
| 
       384 
     | 
    
         
            -
                      settings[:analysis][:analyzer][ 
     | 
| 
      
 399 
     | 
    
         
            +
                      settings[:analysis][:analyzer][default_analyzer][:filter].insert(4, "searchkick_synonym")
         
     | 
| 
      
 400 
     | 
    
         
            +
                      settings[:analysis][:analyzer][default_analyzer][:filter] << "searchkick_synonym"
         
     | 
| 
       385 
401 
     | 
    
         | 
| 
       386 
402 
     | 
    
         
             
                      %w(word_start word_middle word_end).each do |type|
         
     | 
| 
       387 
403 
     | 
    
         
             
                        settings[:analysis][:analyzer]["searchkick_#{type}_index".to_sym][:filter].insert(2, "searchkick_synonym")
         
     | 
| 
         @@ -395,8 +411,8 @@ module Searchkick 
     | 
|
| 
       395 
411 
     | 
    
         
             
                        synonyms_path: Searchkick.wordnet_path
         
     | 
| 
       396 
412 
     | 
    
         
             
                      }
         
     | 
| 
       397 
413 
     | 
    
         | 
| 
       398 
     | 
    
         
            -
                      settings[:analysis][:analyzer][ 
     | 
| 
       399 
     | 
    
         
            -
                      settings[:analysis][:analyzer][ 
     | 
| 
      
 414 
     | 
    
         
            +
                      settings[:analysis][:analyzer][default_analyzer][:filter].insert(4, "searchkick_wordnet")
         
     | 
| 
      
 415 
     | 
    
         
            +
                      settings[:analysis][:analyzer][default_analyzer][:filter] << "searchkick_wordnet"
         
     | 
| 
       400 
416 
     | 
    
         | 
| 
       401 
417 
     | 
    
         
             
                      %w(word_start word_middle word_end).each do |type|
         
     | 
| 
       402 
418 
     | 
    
         
             
                        settings[:analysis][:analyzer]["searchkick_#{type}_index".to_sym][:filter].insert(2, "searchkick_wordnet")
         
     | 
| 
         @@ -416,7 +432,7 @@ module Searchkick 
     | 
|
| 
       416 
432 
     | 
    
         
             
                      mapping[conversions_field] = {
         
     | 
| 
       417 
433 
     | 
    
         
             
                        type: "nested",
         
     | 
| 
       418 
434 
     | 
    
         
             
                        properties: {
         
     | 
| 
       419 
     | 
    
         
            -
                          query: {type:  
     | 
| 
      
 435 
     | 
    
         
            +
                          query: {type: default_type, analyzer: "searchkick_keyword"},
         
     | 
| 
       420 
436 
     | 
    
         
             
                          count: {type: "integer"}
         
     | 
| 
       421 
437 
     | 
    
         
             
                        }
         
     | 
| 
       422 
438 
     | 
    
         
             
                      }
         
     | 
| 
         @@ -430,32 +446,39 @@ module Searchkick 
     | 
|
| 
       430 
446 
     | 
    
         
             
                    word = options[:word] != false && (!options[:match] || options[:match] == :word)
         
     | 
| 
       431 
447 
     | 
    
         | 
| 
       432 
448 
     | 
    
         
             
                    mapping_options.values.flatten.uniq.each do |field|
         
     | 
| 
       433 
     | 
    
         
            -
                       
     | 
| 
       434 
     | 
    
         
            -
                        type: "multi_field",
         
     | 
| 
       435 
     | 
    
         
            -
                        fields: {}
         
     | 
| 
       436 
     | 
    
         
            -
                      }
         
     | 
| 
      
 449 
     | 
    
         
            +
                      fields = {}
         
     | 
| 
       437 
450 
     | 
    
         | 
| 
       438 
     | 
    
         
            -
                       
     | 
| 
       439 
     | 
    
         
            -
                         
     | 
| 
      
 451 
     | 
    
         
            +
                      if mapping_options[:only_analyzed].include?(field)
         
     | 
| 
      
 452 
     | 
    
         
            +
                        fields[field] = {type: default_type, index: "no"}
         
     | 
| 
      
 453 
     | 
    
         
            +
                      else
         
     | 
| 
      
 454 
     | 
    
         
            +
                        fields[field] = keyword_mapping
         
     | 
| 
       440 
455 
     | 
    
         
             
                      end
         
     | 
| 
       441 
456 
     | 
    
         | 
| 
       442 
457 
     | 
    
         
             
                      if !options[:searchable] || mapping_options[:searchable].include?(field)
         
     | 
| 
       443 
458 
     | 
    
         
             
                        if word
         
     | 
| 
       444 
     | 
    
         
            -
                           
     | 
| 
      
 459 
     | 
    
         
            +
                          fields["analyzed"] = {type: default_type, index: "analyzed", analyzer: default_analyzer}
         
     | 
| 
       445 
460 
     | 
    
         | 
| 
       446 
461 
     | 
    
         
             
                          if mapping_options[:highlight].include?(field)
         
     | 
| 
       447 
     | 
    
         
            -
                             
     | 
| 
      
 462 
     | 
    
         
            +
                            fields["analyzed"][:term_vector] = "with_positions_offsets"
         
     | 
| 
       448 
463 
     | 
    
         
             
                          end
         
     | 
| 
       449 
464 
     | 
    
         
             
                        end
         
     | 
| 
       450 
465 
     | 
    
         | 
| 
       451 
     | 
    
         
            -
                        mapping_options.except(:highlight, :searchable, :only_analyzed).each do |type,  
     | 
| 
       452 
     | 
    
         
            -
                          if options[:match] == type ||  
     | 
| 
       453 
     | 
    
         
            -
                             
     | 
| 
      
 466 
     | 
    
         
            +
                        mapping_options.except(:highlight, :searchable, :only_analyzed).each do |type, f|
         
     | 
| 
      
 467 
     | 
    
         
            +
                          if options[:match] == type || f.include?(field)
         
     | 
| 
      
 468 
     | 
    
         
            +
                            fields[type] = {type: default_type, index: "analyzed", analyzer: "searchkick_#{type}_index"}
         
     | 
| 
       454 
469 
     | 
    
         
             
                          end
         
     | 
| 
       455 
470 
     | 
    
         
             
                        end
         
     | 
| 
       456 
471 
     | 
    
         
             
                      end
         
     | 
| 
       457 
472 
     | 
    
         | 
| 
       458 
     | 
    
         
            -
                      mapping[field] = 
     | 
| 
      
 473 
     | 
    
         
            +
                      mapping[field] =
         
     | 
| 
      
 474 
     | 
    
         
            +
                        if below50
         
     | 
| 
      
 475 
     | 
    
         
            +
                          {
         
     | 
| 
      
 476 
     | 
    
         
            +
                            type: "multi_field",
         
     | 
| 
      
 477 
     | 
    
         
            +
                            fields: fields
         
     | 
| 
      
 478 
     | 
    
         
            +
                          }
         
     | 
| 
      
 479 
     | 
    
         
            +
                        elsif fields[field]
         
     | 
| 
      
 480 
     | 
    
         
            +
                          fields[field].merge(fields: fields.except(field))
         
     | 
| 
      
 481 
     | 
    
         
            +
                       end
         
     | 
| 
       459 
482 
     | 
    
         
             
                    end
         
     | 
| 
       460 
483 
     | 
    
         | 
| 
       461 
484 
     | 
    
         
             
                    (options[:locations] || []).map(&:to_s).each do |field|
         
     | 
| 
         @@ -466,7 +489,7 @@ module Searchkick 
     | 
|
| 
       466 
489 
     | 
    
         | 
| 
       467 
490 
     | 
    
         
             
                    (options[:unsearchable] || []).map(&:to_s).each do |field|
         
     | 
| 
       468 
491 
     | 
    
         
             
                      mapping[field] = {
         
     | 
| 
       469 
     | 
    
         
            -
                        type:  
     | 
| 
      
 492 
     | 
    
         
            +
                        type: default_type,
         
     | 
| 
       470 
493 
     | 
    
         
             
                        index: "no"
         
     | 
| 
       471 
494 
     | 
    
         
             
                      }
         
     | 
| 
       472 
495 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -484,21 +507,35 @@ module Searchkick 
     | 
|
| 
       484 
507 
     | 
    
         
             
                      # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
         
     | 
| 
       485 
508 
     | 
    
         
             
                      # however, we can include the not_analyzed field in _all
         
     | 
| 
       486 
509 
     | 
    
         
             
                      # and the _all index analyzer will take care of it
         
     | 
| 
       487 
     | 
    
         
            -
                      "{name}" =>  
     | 
| 
      
 510 
     | 
    
         
            +
                      "{name}" => keyword_mapping.merge(include_in_all: !options[:searchable])
         
     | 
| 
       488 
511 
     | 
    
         
             
                    }
         
     | 
| 
       489 
512 
     | 
    
         | 
| 
      
 513 
     | 
    
         
            +
                    dynamic_fields["{name}"][:ignore_above] = 256 unless below22
         
     | 
| 
      
 514 
     | 
    
         
            +
             
     | 
| 
       490 
515 
     | 
    
         
             
                    unless options[:searchable]
         
     | 
| 
       491 
516 
     | 
    
         
             
                      if options[:match] && options[:match] != :word
         
     | 
| 
       492 
     | 
    
         
            -
                        dynamic_fields[options[:match]] = {type:  
     | 
| 
      
 517 
     | 
    
         
            +
                        dynamic_fields[options[:match]] = {type: default_type, index: "analyzed", analyzer: "searchkick_#{options[:match]}_index"}
         
     | 
| 
       493 
518 
     | 
    
         
             
                      end
         
     | 
| 
       494 
519 
     | 
    
         | 
| 
       495 
520 
     | 
    
         
             
                      if word
         
     | 
| 
       496 
     | 
    
         
            -
                        dynamic_fields["analyzed"] = {type:  
     | 
| 
      
 521 
     | 
    
         
            +
                        dynamic_fields["analyzed"] = {type: default_type, index: "analyzed"}
         
     | 
| 
       497 
522 
     | 
    
         
             
                      end
         
     | 
| 
       498 
523 
     | 
    
         
             
                    end
         
     | 
| 
       499 
524 
     | 
    
         | 
| 
      
 525 
     | 
    
         
            +
                    # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
         
     | 
| 
      
 526 
     | 
    
         
            +
                    multi_field =
         
     | 
| 
      
 527 
     | 
    
         
            +
                      if below50
         
     | 
| 
      
 528 
     | 
    
         
            +
                        {
         
     | 
| 
      
 529 
     | 
    
         
            +
                          type: "multi_field",
         
     | 
| 
      
 530 
     | 
    
         
            +
                          fields: dynamic_fields
         
     | 
| 
      
 531 
     | 
    
         
            +
                        }
         
     | 
| 
      
 532 
     | 
    
         
            +
                      else
         
     | 
| 
      
 533 
     | 
    
         
            +
                        dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}"))
         
     | 
| 
      
 534 
     | 
    
         
            +
                      end
         
     | 
| 
      
 535 
     | 
    
         
            +
             
     | 
| 
       500 
536 
     | 
    
         
             
                    mappings = {
         
     | 
| 
       501 
537 
     | 
    
         
             
                      _default_: {
         
     | 
| 
      
 538 
     | 
    
         
            +
                        _all: {type: default_type, index: "analyzed", analyzer: default_analyzer},
         
     | 
| 
       502 
539 
     | 
    
         
             
                        properties: mapping,
         
     | 
| 
       503 
540 
     | 
    
         
             
                        _routing: routing,
         
     | 
| 
       504 
541 
     | 
    
         
             
                        # https://gist.github.com/kimchy/2898285
         
     | 
| 
         @@ -507,11 +544,7 @@ module Searchkick 
     | 
|
| 
       507 
544 
     | 
    
         
             
                            string_template: {
         
     | 
| 
       508 
545 
     | 
    
         
             
                              match: "*",
         
     | 
| 
       509 
546 
     | 
    
         
             
                              match_mapping_type: "string",
         
     | 
| 
       510 
     | 
    
         
            -
                              mapping:  
     | 
| 
       511 
     | 
    
         
            -
                                # http://www.elasticsearch.org/guide/reference/mapping/multi-field-type/
         
     | 
| 
       512 
     | 
    
         
            -
                                type: "multi_field",
         
     | 
| 
       513 
     | 
    
         
            -
                                fields: dynamic_fields
         
     | 
| 
       514 
     | 
    
         
            -
                              }
         
     | 
| 
      
 547 
     | 
    
         
            +
                              mapping: multi_field
         
     | 
| 
       515 
548 
     | 
    
         
             
                            }
         
     | 
| 
       516 
549 
     | 
    
         
             
                          }
         
     | 
| 
       517 
550 
     | 
    
         
             
                        ]
         
     | 
    
        data/lib/searchkick/model.rb
    CHANGED
    
    | 
         @@ -15,7 +15,9 @@ module Searchkick 
     | 
|
| 
       15 
15 
     | 
    
         
             
                    class_variable_set :@@searchkick_options, options.dup
         
     | 
| 
       16 
16 
     | 
    
         
             
                    class_variable_set :@@searchkick_klass, self
         
     | 
| 
       17 
17 
     | 
    
         
             
                    class_variable_set :@@searchkick_callbacks, callbacks
         
     | 
| 
       18 
     | 
    
         
            -
                    class_variable_set :@@searchkick_index, options[:index_name] || 
     | 
| 
      
 18 
     | 
    
         
            +
                    class_variable_set :@@searchkick_index, options[:index_name] ||
         
     | 
| 
      
 19 
     | 
    
         
            +
                      (options[:index_prefix].respond_to?(:call) && proc { [options[:index_prefix].call, model_name.plural, Searchkick.env].compact.join("_") }) ||
         
     | 
| 
      
 20 
     | 
    
         
            +
                      [options[:index_prefix], model_name.plural, Searchkick.env].compact.join("_")
         
     | 
| 
       19 
21 
     | 
    
         | 
| 
       20 
22 
     | 
    
         
             
                    class << self
         
     | 
| 
       21 
23 
     | 
    
         
             
                      def searchkick_search(term = nil, options = {}, &block)
         
     | 
    
        data/lib/searchkick/query.rb
    CHANGED
    
    | 
         @@ -149,28 +149,7 @@ module Searchkick 
     | 
|
| 
       149 
149 
     | 
    
         
             
                end
         
     | 
| 
       150 
150 
     | 
    
         | 
| 
       151 
151 
     | 
    
         
             
                def prepare
         
     | 
| 
       152 
     | 
    
         
            -
                  boost_fields =  
     | 
| 
       153 
     | 
    
         
            -
                  fields = options[:fields] || searchkick_options[:searchable]
         
     | 
| 
       154 
     | 
    
         
            -
                  fields =
         
     | 
| 
       155 
     | 
    
         
            -
                    if fields
         
     | 
| 
       156 
     | 
    
         
            -
                      if options[:autocomplete]
         
     | 
| 
       157 
     | 
    
         
            -
                        fields.map { |f| "#{f}.autocomplete" }
         
     | 
| 
       158 
     | 
    
         
            -
                      else
         
     | 
| 
       159 
     | 
    
         
            -
                        fields.map do |value|
         
     | 
| 
       160 
     | 
    
         
            -
                          k, v = value.is_a?(Hash) ? value.to_a.first : [value, options[:match] || searchkick_options[:match] || :word]
         
     | 
| 
       161 
     | 
    
         
            -
                          k2, boost = k.to_s.split("^", 2)
         
     | 
| 
       162 
     | 
    
         
            -
                          field = "#{k2}.#{v == :word ? 'analyzed' : v}"
         
     | 
| 
       163 
     | 
    
         
            -
                          boost_fields[field] = boost.to_f if boost
         
     | 
| 
       164 
     | 
    
         
            -
                          field
         
     | 
| 
       165 
     | 
    
         
            -
                        end
         
     | 
| 
       166 
     | 
    
         
            -
                      end
         
     | 
| 
       167 
     | 
    
         
            -
                    else
         
     | 
| 
       168 
     | 
    
         
            -
                      if options[:autocomplete]
         
     | 
| 
       169 
     | 
    
         
            -
                        (searchkick_options[:autocomplete] || []).map { |f| "#{f}.autocomplete" }
         
     | 
| 
       170 
     | 
    
         
            -
                      else
         
     | 
| 
       171 
     | 
    
         
            -
                        ["_all"]
         
     | 
| 
       172 
     | 
    
         
            -
                      end
         
     | 
| 
       173 
     | 
    
         
            -
                    end
         
     | 
| 
      
 152 
     | 
    
         
            +
                  boost_fields, fields = set_fields
         
     | 
| 
       174 
153 
     | 
    
         | 
| 
       175 
154 
     | 
    
         
             
                  operator = options[:operator] || (options[:partial] ? "or" : "and")
         
     | 
| 
       176 
155 
     | 
    
         | 
| 
         @@ -187,7 +166,6 @@ module Searchkick 
     | 
|
| 
       187 
166 
     | 
    
         
             
                  personalize_field = searchkick_options[:personalize]
         
     | 
| 
       188 
167 
     | 
    
         | 
| 
       189 
168 
     | 
    
         
             
                  all = term == "*"
         
     | 
| 
       190 
     | 
    
         
            -
                  facet_limits = {}
         
     | 
| 
       191 
169 
     | 
    
         | 
| 
       192 
170 
     | 
    
         
             
                  options[:json] ||= options[:body]
         
     | 
| 
       193 
171 
     | 
    
         
             
                  if options[:json]
         
     | 
| 
         @@ -256,10 +234,19 @@ module Searchkick 
     | 
|
| 
       256 
234 
     | 
    
         
             
                          factor = boost_fields[field] || 1
         
     | 
| 
       257 
235 
     | 
    
         
             
                          shared_options = {
         
     | 
| 
       258 
236 
     | 
    
         
             
                            query: term,
         
     | 
| 
       259 
     | 
    
         
            -
                            operator: operator,
         
     | 
| 
       260 
237 
     | 
    
         
             
                            boost: 10 * factor
         
     | 
| 
       261 
238 
     | 
    
         
             
                          }
         
     | 
| 
       262 
239 
     | 
    
         | 
| 
      
 240 
     | 
    
         
            +
                          match_type =
         
     | 
| 
      
 241 
     | 
    
         
            +
                            if field.end_with?(".phrase")
         
     | 
| 
      
 242 
     | 
    
         
            +
                              field = field.sub(/\.phrase\z/, ".analyzed")
         
     | 
| 
      
 243 
     | 
    
         
            +
                              :match_phrase
         
     | 
| 
      
 244 
     | 
    
         
            +
                            else
         
     | 
| 
      
 245 
     | 
    
         
            +
                              :match
         
     | 
| 
      
 246 
     | 
    
         
            +
                            end
         
     | 
| 
      
 247 
     | 
    
         
            +
             
     | 
| 
      
 248 
     | 
    
         
            +
                          shared_options[:operator] = operator if match_type == :match || below50?
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
       263 
250 
     | 
    
         
             
                          if field == "_all" || field.end_with?(".analyzed")
         
     | 
| 
       264 
251 
     | 
    
         
             
                            shared_options[:cutoff_frequency] = 0.001 unless operator == "and" || misspellings == false
         
     | 
| 
       265 
252 
     | 
    
         
             
                            qs.concat [
         
     | 
| 
         @@ -274,11 +261,11 @@ module Searchkick 
     | 
|
| 
       274 
261 
     | 
    
         
             
                            qs << shared_options.merge(analyzer: analyzer)
         
     | 
| 
       275 
262 
     | 
    
         
             
                          end
         
     | 
| 
       276 
263 
     | 
    
         | 
| 
       277 
     | 
    
         
            -
                          if misspellings != false
         
     | 
| 
      
 264 
     | 
    
         
            +
                          if misspellings != false && (match_type == :match || below50?)
         
     | 
| 
       278 
265 
     | 
    
         
             
                            qs.concat qs.map { |q| q.except(:cutoff_frequency).merge(fuzziness: edit_distance, prefix_length: prefix_length, max_expansions: max_expansions, boost: factor).merge(transpositions) }
         
     | 
| 
       279 
266 
     | 
    
         
             
                          end
         
     | 
| 
       280 
267 
     | 
    
         | 
| 
       281 
     | 
    
         
            -
                          queries.concat(qs.map { |q| { 
     | 
| 
      
 268 
     | 
    
         
            +
                          queries.concat(qs.map { |q| {match_type => {field => q}} })
         
     | 
| 
       282 
269 
     | 
    
         
             
                        end
         
     | 
| 
       283 
270 
     | 
    
         | 
| 
       284 
271 
     | 
    
         
             
                        payload = {
         
     | 
| 
         @@ -324,52 +311,9 @@ module Searchkick 
     | 
|
| 
       324 
311 
     | 
    
         
             
                    custom_filters = []
         
     | 
| 
       325 
312 
     | 
    
         
             
                    multiply_filters = []
         
     | 
| 
       326 
313 
     | 
    
         | 
| 
       327 
     | 
    
         
            -
                     
     | 
| 
       328 
     | 
    
         
            -
             
     | 
| 
       329 
     | 
    
         
            -
                    if  
     | 
| 
       330 
     | 
    
         
            -
                      boost_by = Hash[boost_by.map { |f| [f, {factor: 1}] }]
         
     | 
| 
       331 
     | 
    
         
            -
                    elsif boost_by.is_a?(Hash)
         
     | 
| 
       332 
     | 
    
         
            -
                      multiply_by, boost_by = boost_by.partition { |_, v| v[:boost_mode] == "multiply" }.map { |i| Hash[i] }
         
     | 
| 
       333 
     | 
    
         
            -
                    end
         
     | 
| 
       334 
     | 
    
         
            -
                    boost_by[options[:boost]] = {factor: 1} if options[:boost]
         
     | 
| 
       335 
     | 
    
         
            -
             
     | 
| 
       336 
     | 
    
         
            -
                    custom_filters.concat boost_filters(boost_by, log: true)
         
     | 
| 
       337 
     | 
    
         
            -
                    multiply_filters.concat boost_filters(multiply_by || {})
         
     | 
| 
       338 
     | 
    
         
            -
             
     | 
| 
       339 
     | 
    
         
            -
                    boost_where = options[:boost_where] || {}
         
     | 
| 
       340 
     | 
    
         
            -
                    if options[:user_id] && personalize_field
         
     | 
| 
       341 
     | 
    
         
            -
                      boost_where[personalize_field] = options[:user_id]
         
     | 
| 
       342 
     | 
    
         
            -
                    end
         
     | 
| 
       343 
     | 
    
         
            -
                    if options[:personalize]
         
     | 
| 
       344 
     | 
    
         
            -
                      boost_where = boost_where.merge(options[:personalize])
         
     | 
| 
       345 
     | 
    
         
            -
                    end
         
     | 
| 
       346 
     | 
    
         
            -
                    boost_where.each do |field, value|
         
     | 
| 
       347 
     | 
    
         
            -
                      if value.is_a?(Array) && value.first.is_a?(Hash)
         
     | 
| 
       348 
     | 
    
         
            -
                        value.each do |value_factor|
         
     | 
| 
       349 
     | 
    
         
            -
                          custom_filters << custom_filter(field, value_factor[:value], value_factor[:factor])
         
     | 
| 
       350 
     | 
    
         
            -
                        end
         
     | 
| 
       351 
     | 
    
         
            -
                      elsif value.is_a?(Hash)
         
     | 
| 
       352 
     | 
    
         
            -
                        custom_filters << custom_filter(field, value[:value], value[:factor])
         
     | 
| 
       353 
     | 
    
         
            -
                      else
         
     | 
| 
       354 
     | 
    
         
            -
                        factor = 1000
         
     | 
| 
       355 
     | 
    
         
            -
                        custom_filters << custom_filter(field, value, factor)
         
     | 
| 
       356 
     | 
    
         
            -
                      end
         
     | 
| 
       357 
     | 
    
         
            -
                    end
         
     | 
| 
       358 
     | 
    
         
            -
             
     | 
| 
       359 
     | 
    
         
            -
                    boost_by_distance = options[:boost_by_distance]
         
     | 
| 
       360 
     | 
    
         
            -
                    if boost_by_distance
         
     | 
| 
       361 
     | 
    
         
            -
                      boost_by_distance = {function: :gauss, scale: "5mi"}.merge(boost_by_distance)
         
     | 
| 
       362 
     | 
    
         
            -
                      if !boost_by_distance[:field] || !boost_by_distance[:origin]
         
     | 
| 
       363 
     | 
    
         
            -
                        raise ArgumentError, "boost_by_distance requires :field and :origin"
         
     | 
| 
       364 
     | 
    
         
            -
                      end
         
     | 
| 
       365 
     | 
    
         
            -
                      function_params = boost_by_distance.select { |k, _| [:origin, :scale, :offset, :decay].include?(k) }
         
     | 
| 
       366 
     | 
    
         
            -
                      function_params[:origin] = location_value(function_params[:origin])
         
     | 
| 
       367 
     | 
    
         
            -
                      custom_filters << {
         
     | 
| 
       368 
     | 
    
         
            -
                        boost_by_distance[:function] => {
         
     | 
| 
       369 
     | 
    
         
            -
                          boost_by_distance[:field] => function_params
         
     | 
| 
       370 
     | 
    
         
            -
                        }
         
     | 
| 
       371 
     | 
    
         
            -
                      }
         
     | 
| 
       372 
     | 
    
         
            -
                    end
         
     | 
| 
      
 314 
     | 
    
         
            +
                    set_boost_by(multiply_filters, custom_filters)
         
     | 
| 
      
 315 
     | 
    
         
            +
                    set_boost_where(custom_filters, personalize_field)
         
     | 
| 
      
 316 
     | 
    
         
            +
                    set_boost_by_distance(custom_filters) if options[:boost_by_distance]
         
     | 
| 
       373 
317 
     | 
    
         | 
| 
       374 
318 
     | 
    
         
             
                    if custom_filters.any?
         
     | 
| 
       375 
319 
     | 
    
         
             
                      payload = {
         
     | 
| 
         @@ -399,187 +343,23 @@ module Searchkick 
     | 
|
| 
       399 
343 
     | 
    
         
             
                    payload[:explain] = options[:explain] if options[:explain]
         
     | 
| 
       400 
344 
     | 
    
         | 
| 
       401 
345 
     | 
    
         
             
                    # order
         
     | 
| 
       402 
     | 
    
         
            -
                    if options[:order]
         
     | 
| 
       403 
     | 
    
         
            -
                      order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc}
         
     | 
| 
       404 
     | 
    
         
            -
                      # TODO id transformation for arrays
         
     | 
| 
       405 
     | 
    
         
            -
                      payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? :_id : k, v] }]
         
     | 
| 
       406 
     | 
    
         
            -
                    end
         
     | 
| 
      
 346 
     | 
    
         
            +
                    set_order(payload) if options[:order]
         
     | 
| 
       407 
347 
     | 
    
         | 
| 
       408 
348 
     | 
    
         
             
                    # filters
         
     | 
| 
       409 
349 
     | 
    
         
             
                    filters = where_filters(options[:where])
         
     | 
| 
       410 
     | 
    
         
            -
                    if filters.any?
         
     | 
| 
       411 
     | 
    
         
            -
                      if options[:facets] || options[:aggs]
         
     | 
| 
       412 
     | 
    
         
            -
                        payload[:filter] = {
         
     | 
| 
       413 
     | 
    
         
            -
                          and: filters
         
     | 
| 
       414 
     | 
    
         
            -
                        }
         
     | 
| 
       415 
     | 
    
         
            -
                      else
         
     | 
| 
       416 
     | 
    
         
            -
                        # more efficient query if no facets
         
     | 
| 
       417 
     | 
    
         
            -
                        payload[:query] = {
         
     | 
| 
       418 
     | 
    
         
            -
                          filtered: {
         
     | 
| 
       419 
     | 
    
         
            -
                            query: payload[:query],
         
     | 
| 
       420 
     | 
    
         
            -
                            filter: {
         
     | 
| 
       421 
     | 
    
         
            -
                              and: filters
         
     | 
| 
       422 
     | 
    
         
            -
                            }
         
     | 
| 
       423 
     | 
    
         
            -
                          }
         
     | 
| 
       424 
     | 
    
         
            -
                        }
         
     | 
| 
       425 
     | 
    
         
            -
                      end
         
     | 
| 
       426 
     | 
    
         
            -
                    end
         
     | 
| 
      
 350 
     | 
    
         
            +
                    set_filters(payload, filters) if filters.any?
         
     | 
| 
       427 
351 
     | 
    
         | 
| 
       428 
352 
     | 
    
         
             
                    # facets
         
     | 
| 
       429 
     | 
    
         
            -
                    if options[:facets]
         
     | 
| 
       430 
     | 
    
         
            -
                      facets = options[:facets] || {}
         
     | 
| 
       431 
     | 
    
         
            -
                      facets = Hash[facets.map { |f| [f, {}] }] if facets.is_a?(Array) # convert to more advanced syntax
         
     | 
| 
       432 
     | 
    
         
            -
             
     | 
| 
       433 
     | 
    
         
            -
                      payload[:facets] = {}
         
     | 
| 
       434 
     | 
    
         
            -
                      facets.each do |field, facet_options|
         
     | 
| 
       435 
     | 
    
         
            -
                        # ask for extra facets due to
         
     | 
| 
       436 
     | 
    
         
            -
                        # https://github.com/elasticsearch/elasticsearch/issues/1305
         
     | 
| 
       437 
     | 
    
         
            -
                        size = facet_options[:limit] ? facet_options[:limit] + 150 : 1_000
         
     | 
| 
       438 
     | 
    
         
            -
             
     | 
| 
       439 
     | 
    
         
            -
                        if facet_options[:ranges]
         
     | 
| 
       440 
     | 
    
         
            -
                          payload[:facets][field] = {
         
     | 
| 
       441 
     | 
    
         
            -
                            range: {
         
     | 
| 
       442 
     | 
    
         
            -
                              field.to_sym => facet_options[:ranges]
         
     | 
| 
       443 
     | 
    
         
            -
                            }
         
     | 
| 
       444 
     | 
    
         
            -
                          }
         
     | 
| 
       445 
     | 
    
         
            -
                        elsif facet_options[:stats]
         
     | 
| 
       446 
     | 
    
         
            -
                          payload[:facets][field] = {
         
     | 
| 
       447 
     | 
    
         
            -
                            terms_stats: {
         
     | 
| 
       448 
     | 
    
         
            -
                              key_field: field,
         
     | 
| 
       449 
     | 
    
         
            -
                              value_script: below14? ? "doc.score" : "_score",
         
     | 
| 
       450 
     | 
    
         
            -
                              size: size
         
     | 
| 
       451 
     | 
    
         
            -
                            }
         
     | 
| 
       452 
     | 
    
         
            -
                          }
         
     | 
| 
       453 
     | 
    
         
            -
                        else
         
     | 
| 
       454 
     | 
    
         
            -
                          payload[:facets][field] = {
         
     | 
| 
       455 
     | 
    
         
            -
                            terms: {
         
     | 
| 
       456 
     | 
    
         
            -
                              field: facet_options[:field] || field,
         
     | 
| 
       457 
     | 
    
         
            -
                              size: size
         
     | 
| 
       458 
     | 
    
         
            -
                            }
         
     | 
| 
       459 
     | 
    
         
            -
                          }
         
     | 
| 
       460 
     | 
    
         
            -
                        end
         
     | 
| 
       461 
     | 
    
         
            -
             
     | 
| 
       462 
     | 
    
         
            -
                        facet_limits[field] = facet_options[:limit] if facet_options[:limit]
         
     | 
| 
       463 
     | 
    
         
            -
             
     | 
| 
       464 
     | 
    
         
            -
                        # offset is not possible
         
     | 
| 
       465 
     | 
    
         
            -
                        # http://elasticsearch-users.115913.n3.nabble.com/Is-pagination-possible-in-termsStatsFacet-td3422943.html
         
     | 
| 
       466 
     | 
    
         
            -
             
     | 
| 
       467 
     | 
    
         
            -
                        facet_options.deep_merge!(where: options.fetch(:where, {}).reject { |k| k == field }) if options[:smart_facets] == true
         
     | 
| 
       468 
     | 
    
         
            -
                        facet_filters = where_filters(facet_options[:where])
         
     | 
| 
       469 
     | 
    
         
            -
                        if facet_filters.any?
         
     | 
| 
       470 
     | 
    
         
            -
                          payload[:facets][field][:facet_filter] = {
         
     | 
| 
       471 
     | 
    
         
            -
                            and: {
         
     | 
| 
       472 
     | 
    
         
            -
                              filters: facet_filters
         
     | 
| 
       473 
     | 
    
         
            -
                            }
         
     | 
| 
       474 
     | 
    
         
            -
                          }
         
     | 
| 
       475 
     | 
    
         
            -
                        end
         
     | 
| 
       476 
     | 
    
         
            -
                      end
         
     | 
| 
       477 
     | 
    
         
            -
                    end
         
     | 
| 
      
 353 
     | 
    
         
            +
                    set_facets(payload) if options[:facets]
         
     | 
| 
       478 
354 
     | 
    
         | 
| 
       479 
355 
     | 
    
         
             
                    # aggregations
         
     | 
| 
       480 
     | 
    
         
            -
                    if options[:aggs]
         
     | 
| 
       481 
     | 
    
         
            -
                      aggs = options[:aggs]
         
     | 
| 
       482 
     | 
    
         
            -
                      payload[:aggs] = {}
         
     | 
| 
       483 
     | 
    
         
            -
             
     | 
| 
       484 
     | 
    
         
            -
                      aggs = Hash[aggs.map { |f| [f, {}] }] if aggs.is_a?(Array) # convert to more advanced syntax
         
     | 
| 
       485 
     | 
    
         
            -
             
     | 
| 
       486 
     | 
    
         
            -
                      aggs.each do |field, agg_options|
         
     | 
| 
       487 
     | 
    
         
            -
                        size = agg_options[:limit] ? agg_options[:limit] : 1_000
         
     | 
| 
       488 
     | 
    
         
            -
                        shared_agg_options = agg_options.slice(:order)
         
     | 
| 
       489 
     | 
    
         
            -
             
     | 
| 
       490 
     | 
    
         
            -
                        if agg_options[:ranges]
         
     | 
| 
       491 
     | 
    
         
            -
                          payload[:aggs][field] = {
         
     | 
| 
       492 
     | 
    
         
            -
                            range: {
         
     | 
| 
       493 
     | 
    
         
            -
                              field: agg_options[:field] || field,
         
     | 
| 
       494 
     | 
    
         
            -
                              ranges: agg_options[:ranges]
         
     | 
| 
       495 
     | 
    
         
            -
                            }.merge(shared_agg_options)
         
     | 
| 
       496 
     | 
    
         
            -
                          }
         
     | 
| 
       497 
     | 
    
         
            -
                        elsif agg_options[:date_ranges]
         
     | 
| 
       498 
     | 
    
         
            -
                          payload[:aggs][field] = {
         
     | 
| 
       499 
     | 
    
         
            -
                            date_range: {
         
     | 
| 
       500 
     | 
    
         
            -
                              field: agg_options[:field] || field,
         
     | 
| 
       501 
     | 
    
         
            -
                              ranges: agg_options[:date_ranges]
         
     | 
| 
       502 
     | 
    
         
            -
                            }.merge(shared_agg_options)
         
     | 
| 
       503 
     | 
    
         
            -
                          }
         
     | 
| 
       504 
     | 
    
         
            -
                        else
         
     | 
| 
       505 
     | 
    
         
            -
                          payload[:aggs][field] = {
         
     | 
| 
       506 
     | 
    
         
            -
                            terms: {
         
     | 
| 
       507 
     | 
    
         
            -
                              field: agg_options[:field] || field,
         
     | 
| 
       508 
     | 
    
         
            -
                              size: size
         
     | 
| 
       509 
     | 
    
         
            -
                            }.merge(shared_agg_options)
         
     | 
| 
       510 
     | 
    
         
            -
                          }
         
     | 
| 
       511 
     | 
    
         
            -
                        end
         
     | 
| 
       512 
     | 
    
         
            -
             
     | 
| 
       513 
     | 
    
         
            -
                        where = {}
         
     | 
| 
       514 
     | 
    
         
            -
                        where = (options[:where] || {}).reject { |k| k == field } unless options[:smart_aggs] == false
         
     | 
| 
       515 
     | 
    
         
            -
                        agg_filters = where_filters(where.merge(agg_options[:where] || {}))
         
     | 
| 
       516 
     | 
    
         
            -
                        if agg_filters.any?
         
     | 
| 
       517 
     | 
    
         
            -
                          payload[:aggs][field] = {
         
     | 
| 
       518 
     | 
    
         
            -
                            filter: {
         
     | 
| 
       519 
     | 
    
         
            -
                              bool: {
         
     | 
| 
       520 
     | 
    
         
            -
                                must: agg_filters
         
     | 
| 
       521 
     | 
    
         
            -
                              }
         
     | 
| 
       522 
     | 
    
         
            -
                            },
         
     | 
| 
       523 
     | 
    
         
            -
                            aggs: {
         
     | 
| 
       524 
     | 
    
         
            -
                              field => payload[:aggs][field]
         
     | 
| 
       525 
     | 
    
         
            -
                            }
         
     | 
| 
       526 
     | 
    
         
            -
                          }
         
     | 
| 
       527 
     | 
    
         
            -
                        end
         
     | 
| 
       528 
     | 
    
         
            -
                      end
         
     | 
| 
       529 
     | 
    
         
            -
                    end
         
     | 
| 
      
 356 
     | 
    
         
            +
                    set_aggregations(payload) if options[:aggs]
         
     | 
| 
       530 
357 
     | 
    
         | 
| 
       531 
358 
     | 
    
         
             
                    # suggestions
         
     | 
| 
       532 
     | 
    
         
            -
                    if options[:suggest]
         
     | 
| 
       533 
     | 
    
         
            -
                      suggest_fields = (searchkick_options[:suggest] || []).map(&:to_s)
         
     | 
| 
       534 
     | 
    
         
            -
             
     | 
| 
       535 
     | 
    
         
            -
                      # intersection
         
     | 
| 
       536 
     | 
    
         
            -
                      if options[:fields]
         
     | 
| 
       537 
     | 
    
         
            -
                        suggest_fields &= options[:fields].map { |v| (v.is_a?(Hash) ? v.keys.first : v).to_s.split("^", 2).first }
         
     | 
| 
       538 
     | 
    
         
            -
                      end
         
     | 
| 
       539 
     | 
    
         
            -
             
     | 
| 
       540 
     | 
    
         
            -
                      if suggest_fields.any?
         
     | 
| 
       541 
     | 
    
         
            -
                        payload[:suggest] = {text: term}
         
     | 
| 
       542 
     | 
    
         
            -
                        suggest_fields.each do |field|
         
     | 
| 
       543 
     | 
    
         
            -
                          payload[:suggest][field] = {
         
     | 
| 
       544 
     | 
    
         
            -
                            phrase: {
         
     | 
| 
       545 
     | 
    
         
            -
                              field: "#{field}.suggest"
         
     | 
| 
       546 
     | 
    
         
            -
                            }
         
     | 
| 
       547 
     | 
    
         
            -
                          }
         
     | 
| 
       548 
     | 
    
         
            -
                        end
         
     | 
| 
       549 
     | 
    
         
            -
                      end
         
     | 
| 
       550 
     | 
    
         
            -
                    end
         
     | 
| 
      
 359 
     | 
    
         
            +
                    set_suggestions(payload) if options[:suggest]
         
     | 
| 
       551 
360 
     | 
    
         | 
| 
       552 
361 
     | 
    
         
             
                    # highlight
         
     | 
| 
       553 
     | 
    
         
            -
                    if options[:highlight]
         
     | 
| 
       554 
     | 
    
         
            -
                      payload[:highlight] = {
         
     | 
| 
       555 
     | 
    
         
            -
                        fields: Hash[fields.map { |f| [f, {}] }]
         
     | 
| 
       556 
     | 
    
         
            -
                      }
         
     | 
| 
       557 
     | 
    
         
            -
             
     | 
| 
       558 
     | 
    
         
            -
                      if options[:highlight].is_a?(Hash)
         
     | 
| 
       559 
     | 
    
         
            -
                        if (tag = options[:highlight][:tag])
         
     | 
| 
       560 
     | 
    
         
            -
                          payload[:highlight][:pre_tags] = [tag]
         
     | 
| 
       561 
     | 
    
         
            -
                          payload[:highlight][:post_tags] = [tag.to_s.gsub(/\A</, "</")]
         
     | 
| 
       562 
     | 
    
         
            -
                        end
         
     | 
| 
       563 
     | 
    
         
            -
             
     | 
| 
       564 
     | 
    
         
            -
                        if (fragment_size = options[:highlight][:fragment_size])
         
     | 
| 
       565 
     | 
    
         
            -
                          payload[:highlight][:fragment_size] = fragment_size
         
     | 
| 
       566 
     | 
    
         
            -
                        end
         
     | 
| 
       567 
     | 
    
         
            -
                        if (encoder = options[:highlight][:encoder])
         
     | 
| 
       568 
     | 
    
         
            -
                          payload[:highlight][:encoder] = encoder
         
     | 
| 
       569 
     | 
    
         
            -
                        end
         
     | 
| 
       570 
     | 
    
         
            -
             
     | 
| 
       571 
     | 
    
         
            -
                        highlight_fields = options[:highlight][:fields]
         
     | 
| 
       572 
     | 
    
         
            -
                        if highlight_fields
         
     | 
| 
       573 
     | 
    
         
            -
                          payload[:highlight][:fields] = {}
         
     | 
| 
       574 
     | 
    
         
            -
             
     | 
| 
       575 
     | 
    
         
            -
                          highlight_fields.each do |name, opts|
         
     | 
| 
       576 
     | 
    
         
            -
                            payload[:highlight][:fields]["#{name}.#{@match_suffix}"] = opts || {}
         
     | 
| 
       577 
     | 
    
         
            -
                          end
         
     | 
| 
       578 
     | 
    
         
            -
                        end
         
     | 
| 
       579 
     | 
    
         
            -
                      end
         
     | 
| 
       580 
     | 
    
         
            -
             
     | 
| 
       581 
     | 
    
         
            -
                      @highlighted_fields = payload[:highlight][:fields].keys
         
     | 
| 
       582 
     | 
    
         
            -
                    end
         
     | 
| 
      
 362 
     | 
    
         
            +
                    set_highlights(payload, fields) if options[:highlight]
         
     | 
| 
       583 
363 
     | 
    
         | 
| 
       584 
364 
     | 
    
         
             
                    # An empty array will cause only the _id and _type for each hit to be returned
         
     | 
| 
       585 
365 
     | 
    
         
             
                    # doc for :select - http://www.elasticsearch.org/guide/reference/api/search/fields/
         
     | 
| 
         @@ -606,13 +386,286 @@ module Searchkick 
     | 
|
| 
       606 
386 
     | 
    
         
             
                  end
         
     | 
| 
       607 
387 
     | 
    
         | 
| 
       608 
388 
     | 
    
         
             
                  @body = payload
         
     | 
| 
       609 
     | 
    
         
            -
                  @facet_limits = facet_limits
         
     | 
| 
      
 389 
     | 
    
         
            +
                  @facet_limits = @facet_limits || {}
         
     | 
| 
       610 
390 
     | 
    
         
             
                  @page = page
         
     | 
| 
       611 
391 
     | 
    
         
             
                  @per_page = per_page
         
     | 
| 
       612 
392 
     | 
    
         
             
                  @padding = padding
         
     | 
| 
       613 
393 
     | 
    
         
             
                  @load = load
         
     | 
| 
       614 
394 
     | 
    
         
             
                end
         
     | 
| 
       615 
395 
     | 
    
         | 
| 
      
 396 
     | 
    
         
            +
                def set_fields
         
     | 
| 
      
 397 
     | 
    
         
            +
                  boost_fields = {}
         
     | 
| 
      
 398 
     | 
    
         
            +
                  fields = options[:fields] || searchkick_options[:searchable]
         
     | 
| 
      
 399 
     | 
    
         
            +
                  fields =
         
     | 
| 
      
 400 
     | 
    
         
            +
                    if fields
         
     | 
| 
      
 401 
     | 
    
         
            +
                      if options[:autocomplete]
         
     | 
| 
      
 402 
     | 
    
         
            +
                        fields.map { |f| "#{f}.autocomplete" }
         
     | 
| 
      
 403 
     | 
    
         
            +
                      else
         
     | 
| 
      
 404 
     | 
    
         
            +
                        fields.map do |value|
         
     | 
| 
      
 405 
     | 
    
         
            +
                          k, v = value.is_a?(Hash) ? value.to_a.first : [value, options[:match] || searchkick_options[:match] || :word]
         
     | 
| 
      
 406 
     | 
    
         
            +
                          k2, boost = k.to_s.split("^", 2)
         
     | 
| 
      
 407 
     | 
    
         
            +
                          field = "#{k2}.#{v == :word ? 'analyzed' : v}"
         
     | 
| 
      
 408 
     | 
    
         
            +
                          boost_fields[field] = boost.to_f if boost
         
     | 
| 
      
 409 
     | 
    
         
            +
                          field
         
     | 
| 
      
 410 
     | 
    
         
            +
                        end
         
     | 
| 
      
 411 
     | 
    
         
            +
                      end
         
     | 
| 
      
 412 
     | 
    
         
            +
                    else
         
     | 
| 
      
 413 
     | 
    
         
            +
                      if options[:autocomplete]
         
     | 
| 
      
 414 
     | 
    
         
            +
                        (searchkick_options[:autocomplete] || []).map { |f| "#{f}.autocomplete" }
         
     | 
| 
      
 415 
     | 
    
         
            +
                      else
         
     | 
| 
      
 416 
     | 
    
         
            +
                        ["_all"]
         
     | 
| 
      
 417 
     | 
    
         
            +
                      end
         
     | 
| 
      
 418 
     | 
    
         
            +
                    end
         
     | 
| 
      
 419 
     | 
    
         
            +
                  [boost_fields, fields]
         
     | 
| 
      
 420 
     | 
    
         
            +
                end
         
     | 
| 
      
 421 
     | 
    
         
            +
             
     | 
| 
      
 422 
     | 
    
         
            +
                def set_boost_by_distance(custom_filters)
         
     | 
| 
      
 423 
     | 
    
         
            +
                  boost_by_distance = options[:boost_by_distance] || {}
         
     | 
| 
      
 424 
     | 
    
         
            +
                  boost_by_distance = {function: :gauss, scale: "5mi"}.merge(boost_by_distance)
         
     | 
| 
      
 425 
     | 
    
         
            +
                  if !boost_by_distance[:field] || !boost_by_distance[:origin]
         
     | 
| 
      
 426 
     | 
    
         
            +
                    raise ArgumentError, "boost_by_distance requires :field and :origin"
         
     | 
| 
      
 427 
     | 
    
         
            +
                  end
         
     | 
| 
      
 428 
     | 
    
         
            +
                  function_params = boost_by_distance.select { |k, _| [:origin, :scale, :offset, :decay].include?(k) }
         
     | 
| 
      
 429 
     | 
    
         
            +
                  function_params[:origin] = location_value(function_params[:origin])
         
     | 
| 
      
 430 
     | 
    
         
            +
                  custom_filters << {
         
     | 
| 
      
 431 
     | 
    
         
            +
                    boost_by_distance[:function] => {
         
     | 
| 
      
 432 
     | 
    
         
            +
                      boost_by_distance[:field] => function_params
         
     | 
| 
      
 433 
     | 
    
         
            +
                    }
         
     | 
| 
      
 434 
     | 
    
         
            +
                  }
         
     | 
| 
      
 435 
     | 
    
         
            +
                end
         
     | 
| 
      
 436 
     | 
    
         
            +
             
     | 
| 
      
 437 
     | 
    
         
            +
                def set_boost_by(multiply_filters, custom_filters)
         
     | 
| 
      
 438 
     | 
    
         
            +
                  boost_by = options[:boost_by] || {}
         
     | 
| 
      
 439 
     | 
    
         
            +
                  if boost_by.is_a?(Array)
         
     | 
| 
      
 440 
     | 
    
         
            +
                    boost_by = Hash[boost_by.map { |f| [f, {factor: 1}] }]
         
     | 
| 
      
 441 
     | 
    
         
            +
                  elsif boost_by.is_a?(Hash)
         
     | 
| 
      
 442 
     | 
    
         
            +
                    multiply_by, boost_by = boost_by.partition { |_, v| v[:boost_mode] == "multiply" }.map { |i| Hash[i] }
         
     | 
| 
      
 443 
     | 
    
         
            +
                  end
         
     | 
| 
      
 444 
     | 
    
         
            +
                  boost_by[options[:boost]] = {factor: 1} if options[:boost]
         
     | 
| 
      
 445 
     | 
    
         
            +
             
     | 
| 
      
 446 
     | 
    
         
            +
                  custom_filters.concat boost_filters(boost_by, log: true)
         
     | 
| 
      
 447 
     | 
    
         
            +
                  multiply_filters.concat boost_filters(multiply_by || {})
         
     | 
| 
      
 448 
     | 
    
         
            +
                end
         
     | 
| 
      
 449 
     | 
    
         
            +
             
     | 
| 
      
 450 
     | 
    
         
            +
                def set_boost_where(custom_filters, personalize_field)
         
     | 
| 
      
 451 
     | 
    
         
            +
                  boost_where = options[:boost_where] || {}
         
     | 
| 
      
 452 
     | 
    
         
            +
                  if options[:user_id] && personalize_field
         
     | 
| 
      
 453 
     | 
    
         
            +
                    boost_where[personalize_field] = options[:user_id]
         
     | 
| 
      
 454 
     | 
    
         
            +
                  end
         
     | 
| 
      
 455 
     | 
    
         
            +
                  if options[:personalize]
         
     | 
| 
      
 456 
     | 
    
         
            +
                    boost_where = boost_where.merge(options[:personalize])
         
     | 
| 
      
 457 
     | 
    
         
            +
                  end
         
     | 
| 
      
 458 
     | 
    
         
            +
                  boost_where.each do |field, value|
         
     | 
| 
      
 459 
     | 
    
         
            +
                    if value.is_a?(Array) && value.first.is_a?(Hash)
         
     | 
| 
      
 460 
     | 
    
         
            +
                      value.each do |value_factor|
         
     | 
| 
      
 461 
     | 
    
         
            +
                        custom_filters << custom_filter(field, value_factor[:value], value_factor[:factor])
         
     | 
| 
      
 462 
     | 
    
         
            +
                      end
         
     | 
| 
      
 463 
     | 
    
         
            +
                    elsif value.is_a?(Hash)
         
     | 
| 
      
 464 
     | 
    
         
            +
                      custom_filters << custom_filter(field, value[:value], value[:factor])
         
     | 
| 
      
 465 
     | 
    
         
            +
                    else
         
     | 
| 
      
 466 
     | 
    
         
            +
                      factor = 1000
         
     | 
| 
      
 467 
     | 
    
         
            +
                      custom_filters << custom_filter(field, value, factor)
         
     | 
| 
      
 468 
     | 
    
         
            +
                    end
         
     | 
| 
      
 469 
     | 
    
         
            +
                  end
         
     | 
| 
      
 470 
     | 
    
         
            +
                end
         
     | 
| 
      
 471 
     | 
    
         
            +
             
     | 
| 
      
 472 
     | 
    
         
            +
                def set_suggestions(payload)
         
     | 
| 
      
 473 
     | 
    
         
            +
                  suggest_fields = (searchkick_options[:suggest] || []).map(&:to_s)
         
     | 
| 
      
 474 
     | 
    
         
            +
             
     | 
| 
      
 475 
     | 
    
         
            +
                  # intersection
         
     | 
| 
      
 476 
     | 
    
         
            +
                  if options[:fields]
         
     | 
| 
      
 477 
     | 
    
         
            +
                    suggest_fields &= options[:fields].map { |v| (v.is_a?(Hash) ? v.keys.first : v).to_s.split("^", 2).first }
         
     | 
| 
      
 478 
     | 
    
         
            +
                  end
         
     | 
| 
      
 479 
     | 
    
         
            +
             
     | 
| 
      
 480 
     | 
    
         
            +
                  if suggest_fields.any?
         
     | 
| 
      
 481 
     | 
    
         
            +
                    payload[:suggest] = {text: term}
         
     | 
| 
      
 482 
     | 
    
         
            +
                    suggest_fields.each do |field|
         
     | 
| 
      
 483 
     | 
    
         
            +
                      payload[:suggest][field] = {
         
     | 
| 
      
 484 
     | 
    
         
            +
                        phrase: {
         
     | 
| 
      
 485 
     | 
    
         
            +
                          field: "#{field}.suggest"
         
     | 
| 
      
 486 
     | 
    
         
            +
                        }
         
     | 
| 
      
 487 
     | 
    
         
            +
                      }
         
     | 
| 
      
 488 
     | 
    
         
            +
                    end
         
     | 
| 
      
 489 
     | 
    
         
            +
                  end
         
     | 
| 
      
 490 
     | 
    
         
            +
                end
         
     | 
| 
      
 491 
     | 
    
         
            +
             
     | 
| 
      
 492 
     | 
    
         
            +
                def set_highlights(payload, fields)
         
     | 
| 
      
 493 
     | 
    
         
            +
                  payload[:highlight] = {
         
     | 
| 
      
 494 
     | 
    
         
            +
                    fields: Hash[fields.map { |f| [f, {}] }]
         
     | 
| 
      
 495 
     | 
    
         
            +
                  }
         
     | 
| 
      
 496 
     | 
    
         
            +
             
     | 
| 
      
 497 
     | 
    
         
            +
                  if options[:highlight].is_a?(Hash)
         
     | 
| 
      
 498 
     | 
    
         
            +
                    if (tag = options[:highlight][:tag])
         
     | 
| 
      
 499 
     | 
    
         
            +
                      payload[:highlight][:pre_tags] = [tag]
         
     | 
| 
      
 500 
     | 
    
         
            +
                      payload[:highlight][:post_tags] = [tag.to_s.gsub(/\A</, "</")]
         
     | 
| 
      
 501 
     | 
    
         
            +
                    end
         
     | 
| 
      
 502 
     | 
    
         
            +
             
     | 
| 
      
 503 
     | 
    
         
            +
                    if (fragment_size = options[:highlight][:fragment_size])
         
     | 
| 
      
 504 
     | 
    
         
            +
                      payload[:highlight][:fragment_size] = fragment_size
         
     | 
| 
      
 505 
     | 
    
         
            +
                    end
         
     | 
| 
      
 506 
     | 
    
         
            +
                    if (encoder = options[:highlight][:encoder])
         
     | 
| 
      
 507 
     | 
    
         
            +
                      payload[:highlight][:encoder] = encoder
         
     | 
| 
      
 508 
     | 
    
         
            +
                    end
         
     | 
| 
      
 509 
     | 
    
         
            +
             
     | 
| 
      
 510 
     | 
    
         
            +
                    highlight_fields = options[:highlight][:fields]
         
     | 
| 
      
 511 
     | 
    
         
            +
                    if highlight_fields
         
     | 
| 
      
 512 
     | 
    
         
            +
                      payload[:highlight][:fields] = {}
         
     | 
| 
      
 513 
     | 
    
         
            +
             
     | 
| 
      
 514 
     | 
    
         
            +
                      highlight_fields.each do |name, opts|
         
     | 
| 
      
 515 
     | 
    
         
            +
                        payload[:highlight][:fields]["#{name}.#{@match_suffix}"] = opts || {}
         
     | 
| 
      
 516 
     | 
    
         
            +
                      end
         
     | 
| 
      
 517 
     | 
    
         
            +
                    end
         
     | 
| 
      
 518 
     | 
    
         
            +
                  end
         
     | 
| 
      
 519 
     | 
    
         
            +
             
     | 
| 
      
 520 
     | 
    
         
            +
                  @highlighted_fields = payload[:highlight][:fields].keys
         
     | 
| 
      
 521 
     | 
    
         
            +
                end
         
     | 
| 
      
 522 
     | 
    
         
            +
             
     | 
| 
      
 523 
     | 
    
         
            +
                def set_aggregations(payload)
         
     | 
| 
      
 524 
     | 
    
         
            +
                  aggs = options[:aggs]
         
     | 
| 
      
 525 
     | 
    
         
            +
                  payload[:aggs] = {}
         
     | 
| 
      
 526 
     | 
    
         
            +
             
     | 
| 
      
 527 
     | 
    
         
            +
                  aggs = Hash[aggs.map { |f| [f, {}] }] if aggs.is_a?(Array) # convert to more advanced syntax
         
     | 
| 
      
 528 
     | 
    
         
            +
             
     | 
| 
      
 529 
     | 
    
         
            +
                  aggs.each do |field, agg_options|
         
     | 
| 
      
 530 
     | 
    
         
            +
                    size = agg_options[:limit] ? agg_options[:limit] : 1_000
         
     | 
| 
      
 531 
     | 
    
         
            +
                    shared_agg_options = agg_options.slice(:order, :min_doc_count)
         
     | 
| 
      
 532 
     | 
    
         
            +
             
     | 
| 
      
 533 
     | 
    
         
            +
                    if agg_options[:ranges]
         
     | 
| 
      
 534 
     | 
    
         
            +
                      payload[:aggs][field] = {
         
     | 
| 
      
 535 
     | 
    
         
            +
                        range: {
         
     | 
| 
      
 536 
     | 
    
         
            +
                          field: agg_options[:field] || field,
         
     | 
| 
      
 537 
     | 
    
         
            +
                          ranges: agg_options[:ranges]
         
     | 
| 
      
 538 
     | 
    
         
            +
                        }.merge(shared_agg_options)
         
     | 
| 
      
 539 
     | 
    
         
            +
                      }
         
     | 
| 
      
 540 
     | 
    
         
            +
                    elsif agg_options[:date_ranges]
         
     | 
| 
      
 541 
     | 
    
         
            +
                      payload[:aggs][field] = {
         
     | 
| 
      
 542 
     | 
    
         
            +
                        date_range: {
         
     | 
| 
      
 543 
     | 
    
         
            +
                          field: agg_options[:field] || field,
         
     | 
| 
      
 544 
     | 
    
         
            +
                          ranges: agg_options[:date_ranges]
         
     | 
| 
      
 545 
     | 
    
         
            +
                        }.merge(shared_agg_options)
         
     | 
| 
      
 546 
     | 
    
         
            +
                      }
         
     | 
| 
      
 547 
     | 
    
         
            +
                    else
         
     | 
| 
      
 548 
     | 
    
         
            +
                      payload[:aggs][field] = {
         
     | 
| 
      
 549 
     | 
    
         
            +
                        terms: {
         
     | 
| 
      
 550 
     | 
    
         
            +
                          field: agg_options[:field] || field,
         
     | 
| 
      
 551 
     | 
    
         
            +
                          size: size
         
     | 
| 
      
 552 
     | 
    
         
            +
                        }.merge(shared_agg_options)
         
     | 
| 
      
 553 
     | 
    
         
            +
                      }
         
     | 
| 
      
 554 
     | 
    
         
            +
                    end
         
     | 
| 
      
 555 
     | 
    
         
            +
             
     | 
| 
      
 556 
     | 
    
         
            +
                    where = {}
         
     | 
| 
      
 557 
     | 
    
         
            +
                    where = (options[:where] || {}).reject { |k| k == field } unless options[:smart_aggs] == false
         
     | 
| 
      
 558 
     | 
    
         
            +
                    agg_filters = where_filters(where.merge(agg_options[:where] || {}))
         
     | 
| 
      
 559 
     | 
    
         
            +
                    if agg_filters.any?
         
     | 
| 
      
 560 
     | 
    
         
            +
                      payload[:aggs][field] = {
         
     | 
| 
      
 561 
     | 
    
         
            +
                        filter: {
         
     | 
| 
      
 562 
     | 
    
         
            +
                          bool: {
         
     | 
| 
      
 563 
     | 
    
         
            +
                            must: agg_filters
         
     | 
| 
      
 564 
     | 
    
         
            +
                          }
         
     | 
| 
      
 565 
     | 
    
         
            +
                        },
         
     | 
| 
      
 566 
     | 
    
         
            +
                        aggs: {
         
     | 
| 
      
 567 
     | 
    
         
            +
                          field => payload[:aggs][field]
         
     | 
| 
      
 568 
     | 
    
         
            +
                        }
         
     | 
| 
      
 569 
     | 
    
         
            +
                      }
         
     | 
| 
      
 570 
     | 
    
         
            +
                    end
         
     | 
| 
      
 571 
     | 
    
         
            +
                  end
         
     | 
| 
      
 572 
     | 
    
         
            +
                end
         
     | 
| 
      
 573 
     | 
    
         
            +
             
     | 
| 
      
 574 
     | 
    
         
            +
                def set_facets(payload)
         
     | 
| 
      
 575 
     | 
    
         
            +
                  facets = options[:facets] || {}
         
     | 
| 
      
 576 
     | 
    
         
            +
                  facets = Hash[facets.map { |f| [f, {}] }] if facets.is_a?(Array) # convert to more advanced syntax
         
     | 
| 
      
 577 
     | 
    
         
            +
                  facet_limits = {}
         
     | 
| 
      
 578 
     | 
    
         
            +
                  payload[:facets] = {}
         
     | 
| 
      
 579 
     | 
    
         
            +
             
     | 
| 
      
 580 
     | 
    
         
            +
                  facets.each do |field, facet_options|
         
     | 
| 
      
 581 
     | 
    
         
            +
                    # ask for extra facets due to
         
     | 
| 
      
 582 
     | 
    
         
            +
                    # https://github.com/elasticsearch/elasticsearch/issues/1305
         
     | 
| 
      
 583 
     | 
    
         
            +
                    size = facet_options[:limit] ? facet_options[:limit] + 150 : 1_000
         
     | 
| 
      
 584 
     | 
    
         
            +
             
     | 
| 
      
 585 
     | 
    
         
            +
                    if facet_options[:ranges]
         
     | 
| 
      
 586 
     | 
    
         
            +
                      payload[:facets][field] = {
         
     | 
| 
      
 587 
     | 
    
         
            +
                        range: {
         
     | 
| 
      
 588 
     | 
    
         
            +
                          field.to_sym => facet_options[:ranges]
         
     | 
| 
      
 589 
     | 
    
         
            +
                        }
         
     | 
| 
      
 590 
     | 
    
         
            +
                      }
         
     | 
| 
      
 591 
     | 
    
         
            +
                    elsif facet_options[:stats]
         
     | 
| 
      
 592 
     | 
    
         
            +
                      payload[:facets][field] = {
         
     | 
| 
      
 593 
     | 
    
         
            +
                        terms_stats: {
         
     | 
| 
      
 594 
     | 
    
         
            +
                          key_field: field,
         
     | 
| 
      
 595 
     | 
    
         
            +
                          value_script: below14? ? "doc.score" : "_score",
         
     | 
| 
      
 596 
     | 
    
         
            +
                          size: size
         
     | 
| 
      
 597 
     | 
    
         
            +
                        }
         
     | 
| 
      
 598 
     | 
    
         
            +
                      }
         
     | 
| 
      
 599 
     | 
    
         
            +
                    else
         
     | 
| 
      
 600 
     | 
    
         
            +
                      payload[:facets][field] = {
         
     | 
| 
      
 601 
     | 
    
         
            +
                        terms: {
         
     | 
| 
      
 602 
     | 
    
         
            +
                          field: facet_options[:field] || field,
         
     | 
| 
      
 603 
     | 
    
         
            +
                          size: size
         
     | 
| 
      
 604 
     | 
    
         
            +
                        }
         
     | 
| 
      
 605 
     | 
    
         
            +
                      }
         
     | 
| 
      
 606 
     | 
    
         
            +
                    end
         
     | 
| 
      
 607 
     | 
    
         
            +
             
     | 
| 
      
 608 
     | 
    
         
            +
                    facet_limits[field] = facet_options[:limit] if facet_options[:limit]
         
     | 
| 
      
 609 
     | 
    
         
            +
             
     | 
| 
      
 610 
     | 
    
         
            +
                    # offset is not possible
         
     | 
| 
      
 611 
     | 
    
         
            +
                    # http://elasticsearch-users.115913.n3.nabble.com/Is-pagination-possible-in-termsStatsFacet-td3422943.html
         
     | 
| 
      
 612 
     | 
    
         
            +
             
     | 
| 
      
 613 
     | 
    
         
            +
                    facet_options.deep_merge!(where: options.fetch(:where, {}).reject { |k| k == field }) if options[:smart_facets] == true
         
     | 
| 
      
 614 
     | 
    
         
            +
                    facet_filters = where_filters(facet_options[:where])
         
     | 
| 
      
 615 
     | 
    
         
            +
                    if facet_filters.any?
         
     | 
| 
      
 616 
     | 
    
         
            +
                      payload[:facets][field][:facet_filter] = {
         
     | 
| 
      
 617 
     | 
    
         
            +
                        and: {
         
     | 
| 
      
 618 
     | 
    
         
            +
                          filters: facet_filters
         
     | 
| 
      
 619 
     | 
    
         
            +
                        }
         
     | 
| 
      
 620 
     | 
    
         
            +
                      }
         
     | 
| 
      
 621 
     | 
    
         
            +
                    end
         
     | 
| 
      
 622 
     | 
    
         
            +
                  end
         
     | 
| 
      
 623 
     | 
    
         
            +
             
     | 
| 
      
 624 
     | 
    
         
            +
                  @facet_limits = facet_limits
         
     | 
| 
      
 625 
     | 
    
         
            +
                end
         
     | 
| 
      
 626 
     | 
    
         
            +
             
     | 
| 
      
 627 
     | 
    
         
            +
                def set_filters(payload, filters)
         
     | 
| 
      
 628 
     | 
    
         
            +
                  if options[:facets] || options[:aggs]
         
     | 
| 
      
 629 
     | 
    
         
            +
                    if below20?
         
     | 
| 
      
 630 
     | 
    
         
            +
                      payload[:filter] = {
         
     | 
| 
      
 631 
     | 
    
         
            +
                        and: filters
         
     | 
| 
      
 632 
     | 
    
         
            +
                      }
         
     | 
| 
      
 633 
     | 
    
         
            +
                    else
         
     | 
| 
      
 634 
     | 
    
         
            +
                      payload[:post_filter] = {
         
     | 
| 
      
 635 
     | 
    
         
            +
                        bool: {
         
     | 
| 
      
 636 
     | 
    
         
            +
                          filter: filters
         
     | 
| 
      
 637 
     | 
    
         
            +
                        }
         
     | 
| 
      
 638 
     | 
    
         
            +
                      }
         
     | 
| 
      
 639 
     | 
    
         
            +
                    end
         
     | 
| 
      
 640 
     | 
    
         
            +
                  else
         
     | 
| 
      
 641 
     | 
    
         
            +
                    # more efficient query if no facets
         
     | 
| 
      
 642 
     | 
    
         
            +
                    if below20?
         
     | 
| 
      
 643 
     | 
    
         
            +
                      payload[:query] = {
         
     | 
| 
      
 644 
     | 
    
         
            +
                        filtered: {
         
     | 
| 
      
 645 
     | 
    
         
            +
                          query: payload[:query],
         
     | 
| 
      
 646 
     | 
    
         
            +
                          filter: {
         
     | 
| 
      
 647 
     | 
    
         
            +
                            and: filters
         
     | 
| 
      
 648 
     | 
    
         
            +
                          }
         
     | 
| 
      
 649 
     | 
    
         
            +
                        }
         
     | 
| 
      
 650 
     | 
    
         
            +
                      }
         
     | 
| 
      
 651 
     | 
    
         
            +
                    else
         
     | 
| 
      
 652 
     | 
    
         
            +
                      payload[:query] = {
         
     | 
| 
      
 653 
     | 
    
         
            +
                        bool: {
         
     | 
| 
      
 654 
     | 
    
         
            +
                          must: payload[:query],
         
     | 
| 
      
 655 
     | 
    
         
            +
                          filter: filters
         
     | 
| 
      
 656 
     | 
    
         
            +
                        }
         
     | 
| 
      
 657 
     | 
    
         
            +
                      }
         
     | 
| 
      
 658 
     | 
    
         
            +
                    end
         
     | 
| 
      
 659 
     | 
    
         
            +
                  end
         
     | 
| 
      
 660 
     | 
    
         
            +
                end
         
     | 
| 
      
 661 
     | 
    
         
            +
             
     | 
| 
      
 662 
     | 
    
         
            +
                # TODO id transformation for arrays
         
     | 
| 
      
 663 
     | 
    
         
            +
                def set_order(payload)
         
     | 
| 
      
 664 
     | 
    
         
            +
                  order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc}
         
     | 
| 
      
 665 
     | 
    
         
            +
                  id_field = below50? ? :_id : :_uid
         
     | 
| 
      
 666 
     | 
    
         
            +
                  payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? id_field : k, v] }]
         
     | 
| 
      
 667 
     | 
    
         
            +
                end
         
     | 
| 
      
 668 
     | 
    
         
            +
             
     | 
| 
       616 
669 
     | 
    
         
             
                def where_filters(where)
         
     | 
| 
       617 
670 
     | 
    
         
             
                  filters = []
         
     | 
| 
       618 
671 
     | 
    
         
             
                  (where || {}).each do |field, value|
         
     | 
| 
         @@ -620,7 +673,11 @@ module Searchkick 
     | 
|
| 
       620 
673 
     | 
    
         | 
| 
       621 
674 
     | 
    
         
             
                    if field == :or
         
     | 
| 
       622 
675 
     | 
    
         
             
                      value.each do |or_clause|
         
     | 
| 
       623 
     | 
    
         
            -
                         
     | 
| 
      
 676 
     | 
    
         
            +
                        if below50?
         
     | 
| 
      
 677 
     | 
    
         
            +
                          filters << {or: or_clause.map { |or_statement| {and: where_filters(or_statement)} }}
         
     | 
| 
      
 678 
     | 
    
         
            +
                        else
         
     | 
| 
      
 679 
     | 
    
         
            +
                          filters << {bool: {should: or_clause.map { |or_statement| {bool: {filter: where_filters(or_statement)}} }}}
         
     | 
| 
      
 680 
     | 
    
         
            +
                        end
         
     | 
| 
       624 
681 
     | 
    
         
             
                      end
         
     | 
| 
       625 
682 
     | 
    
         
             
                    else
         
     | 
| 
       626 
683 
     | 
    
         
             
                      # expand ranges
         
     | 
| 
         @@ -654,7 +711,11 @@ module Searchkick 
     | 
|
| 
       654 
711 
     | 
    
         
             
                          when :regexp # support for regexp queries without using a regexp ruby object
         
     | 
| 
       655 
712 
     | 
    
         
             
                            filters << {regexp: {field => {value: op_value}}}
         
     | 
| 
       656 
713 
     | 
    
         
             
                          when :not # not equal
         
     | 
| 
       657 
     | 
    
         
            -
                             
     | 
| 
      
 714 
     | 
    
         
            +
                            if below50?
         
     | 
| 
      
 715 
     | 
    
         
            +
                              filters << {not: {filter: term_filters(field, op_value)}}
         
     | 
| 
      
 716 
     | 
    
         
            +
                            else
         
     | 
| 
      
 717 
     | 
    
         
            +
                              filters << {bool: {must_not: term_filters(field, op_value)}}
         
     | 
| 
      
 718 
     | 
    
         
            +
                            end
         
     | 
| 
       658 
719 
     | 
    
         
             
                          when :all
         
     | 
| 
       659 
720 
     | 
    
         
             
                            op_value.each do |value|
         
     | 
| 
       660 
721 
     | 
    
         
             
                              filters << term_filters(field, value)
         
     | 
| 
         @@ -694,12 +755,20 @@ module Searchkick 
     | 
|
| 
       694 
755 
     | 
    
         
             
                def term_filters(field, value)
         
     | 
| 
       695 
756 
     | 
    
         
             
                  if value.is_a?(Array) # in query
         
     | 
| 
       696 
757 
     | 
    
         
             
                    if value.any?(&:nil?)
         
     | 
| 
       697 
     | 
    
         
            -
                       
     | 
| 
      
 758 
     | 
    
         
            +
                      if below50?
         
     | 
| 
      
 759 
     | 
    
         
            +
                        {or: [term_filters(field, nil), term_filters(field, value.compact)]}
         
     | 
| 
      
 760 
     | 
    
         
            +
                      else
         
     | 
| 
      
 761 
     | 
    
         
            +
                        {bool: {should: [term_filters(field, nil), term_filters(field, value.compact)]}}
         
     | 
| 
      
 762 
     | 
    
         
            +
                      end
         
     | 
| 
       698 
763 
     | 
    
         
             
                    else
         
     | 
| 
       699 
764 
     | 
    
         
             
                      {in: {field => value}}
         
     | 
| 
       700 
765 
     | 
    
         
             
                    end
         
     | 
| 
       701 
766 
     | 
    
         
             
                  elsif value.nil?
         
     | 
| 
       702 
     | 
    
         
            -
                     
     | 
| 
      
 767 
     | 
    
         
            +
                    if below50?
         
     | 
| 
      
 768 
     | 
    
         
            +
                      {missing: {field: field, existence: true, null_value: true}}
         
     | 
| 
      
 769 
     | 
    
         
            +
                    else
         
     | 
| 
      
 770 
     | 
    
         
            +
                      {bool: {must_not: {exists: {field: field}}}}
         
     | 
| 
      
 771 
     | 
    
         
            +
                    end
         
     | 
| 
       703 
772 
     | 
    
         
             
                  elsif value.is_a?(Regexp)
         
     | 
| 
       704 
773 
     | 
    
         
             
                    {regexp: {field => {value: value.source}}}
         
     | 
| 
       705 
774 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -708,12 +777,19 @@ module Searchkick 
     | 
|
| 
       708 
777 
     | 
    
         
             
                end
         
     | 
| 
       709 
778 
     | 
    
         | 
| 
       710 
779 
     | 
    
         
             
                def custom_filter(field, value, factor)
         
     | 
| 
       711 
     | 
    
         
            -
                   
     | 
| 
       712 
     | 
    
         
            -
                     
     | 
| 
       713 
     | 
    
         
            -
                       
     | 
| 
       714 
     | 
    
         
            -
             
     | 
| 
       715 
     | 
    
         
            -
             
     | 
| 
       716 
     | 
    
         
            -
             
     | 
| 
      
 780 
     | 
    
         
            +
                  if below50?
         
     | 
| 
      
 781 
     | 
    
         
            +
                    {
         
     | 
| 
      
 782 
     | 
    
         
            +
                      filter: {
         
     | 
| 
      
 783 
     | 
    
         
            +
                        and: where_filters(field => value)
         
     | 
| 
      
 784 
     | 
    
         
            +
                      },
         
     | 
| 
      
 785 
     | 
    
         
            +
                      boost_factor: factor
         
     | 
| 
      
 786 
     | 
    
         
            +
                    }
         
     | 
| 
      
 787 
     | 
    
         
            +
                  else
         
     | 
| 
      
 788 
     | 
    
         
            +
                    {
         
     | 
| 
      
 789 
     | 
    
         
            +
                      filter: where_filters(field => value),
         
     | 
| 
      
 790 
     | 
    
         
            +
                      weight: factor
         
     | 
| 
      
 791 
     | 
    
         
            +
                    }
         
     | 
| 
      
 792 
     | 
    
         
            +
                  end
         
     | 
| 
       717 
793 
     | 
    
         
             
                end
         
     | 
| 
       718 
794 
     | 
    
         | 
| 
       719 
795 
     | 
    
         
             
                def boost_filters(boost_by, options = {})
         
     | 
| 
         @@ -747,19 +823,19 @@ module Searchkick 
     | 
|
| 
       747 
823 
     | 
    
         
             
                end
         
     | 
| 
       748 
824 
     | 
    
         | 
| 
       749 
825 
     | 
    
         
             
                def below12?
         
     | 
| 
       750 
     | 
    
         
            -
                   
     | 
| 
      
 826 
     | 
    
         
            +
                  Searchkick.server_below?("1.2.0")
         
     | 
| 
       751 
827 
     | 
    
         
             
                end
         
     | 
| 
       752 
828 
     | 
    
         | 
| 
       753 
829 
     | 
    
         
             
                def below14?
         
     | 
| 
       754 
     | 
    
         
            -
                   
     | 
| 
      
 830 
     | 
    
         
            +
                  Searchkick.server_below?("1.4.0")
         
     | 
| 
       755 
831 
     | 
    
         
             
                end
         
     | 
| 
       756 
832 
     | 
    
         | 
| 
       757 
833 
     | 
    
         
             
                def below20?
         
     | 
| 
       758 
     | 
    
         
            -
                   
     | 
| 
      
 834 
     | 
    
         
            +
                  Searchkick.server_below?("2.0.0")
         
     | 
| 
       759 
835 
     | 
    
         
             
                end
         
     | 
| 
       760 
836 
     | 
    
         | 
| 
       761 
     | 
    
         
            -
                def  
     | 
| 
       762 
     | 
    
         
            -
                   
     | 
| 
      
 837 
     | 
    
         
            +
                def below50?
         
     | 
| 
      
 838 
     | 
    
         
            +
                  Searchkick.server_below?("5.0.0-alpha1")
         
     | 
| 
       763 
839 
     | 
    
         
             
                end
         
     | 
| 
       764 
840 
     | 
    
         
             
              end
         
     | 
| 
       765 
841 
     | 
    
         
             
            end
         
     |