Commit 7ce0440ab4f2fdd02a52b2bcf42fb4f90e668667
1 parent
4054147c
Exists in
master
and in
17 other branches
Added support for Elasticsearch 7
Showing
27 changed files
with
219 additions
and
203 deletions
Show diff stats
.travis.yml
@@ -14,30 +14,24 @@ cache: | @@ -14,30 +14,24 @@ cache: | ||
14 | directories: | 14 | directories: |
15 | - $HOME/elasticsearch | 15 | - $HOME/elasticsearch |
16 | env: | 16 | env: |
17 | - - ELASTICSEARCH_VERSION=6.7.0 | 17 | + - ELASTICSEARCH_VERSION=7.0.0 |
18 | jdk: openjdk10 | 18 | jdk: openjdk10 |
19 | matrix: | 19 | matrix: |
20 | include: | 20 | include: |
21 | - gemfile: Gemfile | 21 | - gemfile: Gemfile |
22 | - gemfile: test/gemfiles/activerecord51.gemfile | 22 | - gemfile: test/gemfiles/activerecord51.gemfile |
23 | - env: ELASTICSEARCH_VERSION=6.0.0 | 23 | + env: ELASTICSEARCH_VERSION=7.0.0 |
24 | - gemfile: test/gemfiles/activerecord50.gemfile | 24 | - gemfile: test/gemfiles/activerecord50.gemfile |
25 | - env: ELASTICSEARCH_VERSION=5.6.10 | ||
26 | - - gemfile: test/gemfiles/activerecord42.gemfile | ||
27 | - env: ELASTICSEARCH_VERSION=5.0.1 | ||
28 | - - gemfile: test/gemfiles/mongoid6.gemfile | 25 | + env: ELASTICSEARCH_VERSION=6.7.0 |
26 | + - gemfile: test/gemfiles/mongoid7.gemfile | ||
27 | + env: ELASTICSEARCH_VERSION=6.0.0 | ||
29 | services: | 28 | services: |
30 | - mongodb | 29 | - mongodb |
31 | - redis-server | 30 | - redis-server |
32 | - - gemfile: test/gemfiles/mongoid5.gemfile | 31 | + - gemfile: test/gemfiles/mongoid6.gemfile |
33 | services: | 32 | services: |
34 | - mongodb | 33 | - mongodb |
35 | - redis-server | 34 | - redis-server |
36 | - - gemfile: Gemfile | ||
37 | - env: ELASTICSEARCH_VERSION=7.0.0-rc1 | ||
38 | - allow_failures: | ||
39 | - - gemfile: Gemfile | ||
40 | - env: ELASTICSEARCH_VERSION=7.0.0-rc1 | ||
41 | notifications: | 35 | notifications: |
42 | email: | 36 | email: |
43 | on_success: never | 37 | on_success: never |
CHANGELOG.md
1 | +## 4.0.0 [unreleased] | ||
2 | + | ||
3 | +- Added support for Elasticsearch 7 | ||
4 | +- Added `models` option | ||
5 | + | ||
6 | +Breaking changes | ||
7 | + | ||
8 | +- Removed support for Elasticsearch 5 | ||
9 | +- Removed support for multi-word synonyms (they no longer work with shingles) | ||
10 | + | ||
1 | ## 3.1.3 | 11 | ## 3.1.3 |
2 | 12 | ||
3 | - Added support for endless ranges | 13 | - Added support for endless ranges |
README.md
@@ -53,7 +53,7 @@ Add this line to your application’s Gemfile: | @@ -53,7 +53,7 @@ Add this line to your application’s Gemfile: | ||
53 | gem 'searchkick' | 53 | gem 'searchkick' |
54 | ``` | 54 | ``` |
55 | 55 | ||
56 | -The latest version works with Elasticsearch 5 and 6. For Elasticsearch 2, use version 2.5.0 and [this readme](https://github.com/ankane/searchkick/blob/v2.5.0/README.md). | 56 | +The latest version works with Elasticsearch 6 and 7. For Elasticsearch 5, use version 3.1.3 and [this readme](https://github.com/ankane/searchkick/blob/v3.1.3/README.md). |
57 | 57 | ||
58 | Add searchkick to models you want to search. | 58 | Add searchkick to models you want to search. |
59 | 59 | ||
@@ -312,13 +312,13 @@ A few languages require plugins: | @@ -312,13 +312,13 @@ A few languages require plugins: | ||
312 | 312 | ||
313 | ```ruby | 313 | ```ruby |
314 | class Product < ApplicationRecord | 314 | class Product < ApplicationRecord |
315 | - searchkick synonyms: [["scallion", "green onion"], ["qtip", "cotton swab"]] | 315 | + searchkick synonyms: [["burger", "hamburger"], ["sneakers", "shoes"]] |
316 | end | 316 | end |
317 | ``` | 317 | ``` |
318 | 318 | ||
319 | Call `Product.reindex` after changing synonyms. | 319 | Call `Product.reindex` after changing synonyms. |
320 | 320 | ||
321 | -Synonyms cannot be more than two words at the moment. | 321 | +Synonyms cannot be multiple words at the moment. |
322 | 322 | ||
323 | To read synonyms from a file, use: | 323 | To read synonyms from a file, use: |
324 | 324 | ||
@@ -796,8 +796,6 @@ Script support | @@ -796,8 +796,6 @@ Script support | ||
796 | Product.search "*", aggs: {color: {script: {source: "'Color: ' + _value"}}} | 796 | Product.search "*", aggs: {color: {script: {source: "'Color: ' + _value"}}} |
797 | ``` | 797 | ``` |
798 | 798 | ||
799 | -**Note:** Use `inline` instead of `source` before Elasticsearch 5.6 | ||
800 | - | ||
801 | Date histogram | 799 | Date histogram |
802 | 800 | ||
803 | ```ruby | 801 | ```ruby |
@@ -924,9 +922,7 @@ You can also index and search geo shapes. | @@ -924,9 +922,7 @@ You can also index and search geo shapes. | ||
924 | 922 | ||
925 | ```ruby | 923 | ```ruby |
926 | class Restaurant < ApplicationRecord | 924 | class Restaurant < ApplicationRecord |
927 | - searchkick geo_shape: { | ||
928 | - bounds: {tree: "geohash", precision: "1km"} | ||
929 | - } | 925 | + searchkick geo_shape: [:bounds] |
930 | 926 | ||
931 | def search_data | 927 | def search_data |
932 | attributes.merge( | 928 | attributes.merge( |
@@ -959,12 +955,6 @@ Not touching the query shape | @@ -959,12 +955,6 @@ Not touching the query shape | ||
959 | Restaurant.search "burger", where: {bounds: {geo_shape: {type: "envelope", relation: "disjoint", coordinates: [{lat: 38, lon: -123}, {lat: 37, lon: -122}]}}} | 955 | Restaurant.search "burger", where: {bounds: {geo_shape: {type: "envelope", relation: "disjoint", coordinates: [{lat: 38, lon: -123}, {lat: 37, lon: -122}]}}} |
960 | ``` | 956 | ``` |
961 | 957 | ||
962 | -Containing the query shape | ||
963 | - | ||
964 | -```ruby | ||
965 | -Restaurant.search "fries", where: {bounds: {geo_shape: {type: "envelope", relation: "contains", coordinates: [{lat: 38, lon: -123}, {lat: 37, lon: -122}]}}} | ||
966 | -``` | ||
967 | - | ||
968 | ## Inheritance | 958 | ## Inheritance |
969 | 959 | ||
970 | Searchkick supports single table inheritance. | 960 | Searchkick supports single table inheritance. |
@@ -1496,21 +1486,15 @@ Then use `products` and `coupons` as typical results. | @@ -1496,21 +1486,15 @@ Then use `products` and `coupons` as typical results. | ||
1496 | 1486 | ||
1497 | **Note:** Errors are not raised as with single requests. Use the `error` method on each query to check for errors. | 1487 | **Note:** Errors are not raised as with single requests. Use the `error` method on each query to check for errors. |
1498 | 1488 | ||
1499 | -## Multiple Indices | 1489 | +## Multiple Models |
1500 | 1490 | ||
1501 | -Search across multiple models/indices with: | 1491 | +Search across multiple models with: |
1502 | 1492 | ||
1503 | ```ruby | 1493 | ```ruby |
1504 | -Searchkick.search "milk", index_name: [Product, Category] | 1494 | +Searchkick.search "milk", models: [Product, Category] |
1505 | ``` | 1495 | ``` |
1506 | 1496 | ||
1507 | -Specify conditions for different indices | ||
1508 | - | ||
1509 | -```ruby | ||
1510 | -where: {_or: [{_type: "product", in_stock: true}, {_type: "category", active: true}]} | ||
1511 | -``` | ||
1512 | - | ||
1513 | -Boost specific indices with: | 1497 | +Boost specific models with: |
1514 | 1498 | ||
1515 | ```ruby | 1499 | ```ruby |
1516 | indices_boost: {Category => 2, Product => 1} | 1500 | indices_boost: {Category => 2, Product => 1} |
@@ -1657,7 +1641,7 @@ Product.search "milk", includes: [:brand, :stores] | @@ -1657,7 +1641,7 @@ Product.search "milk", includes: [:brand, :stores] | ||
1657 | Eager load different associations by model | 1641 | Eager load different associations by model |
1658 | 1642 | ||
1659 | ```ruby | 1643 | ```ruby |
1660 | -Searchkick.search("*", index_name: [Product, Store], model_includes: {Product => [:store], Store => [:product]}) | 1644 | +Searchkick.search("*", models: [Product, Store], model_includes: {Product => [:store], Store => [:product]}) |
1661 | ``` | 1645 | ``` |
1662 | 1646 | ||
1663 | Run additional scopes on results | 1647 | Run additional scopes on results |
@@ -1900,6 +1884,11 @@ Check out [this great post](https://www.tiagoamaro.com.br/2014/12/11/multi-tenan | @@ -1900,6 +1884,11 @@ Check out [this great post](https://www.tiagoamaro.com.br/2014/12/11/multi-tenan | ||
1900 | 1884 | ||
1901 | See [how to upgrade to Searchkick 3](docs/Searchkick-3-Upgrade.md) | 1885 | See [how to upgrade to Searchkick 3](docs/Searchkick-3-Upgrade.md) |
1902 | 1886 | ||
1887 | +## Elasticsearch 6 to 7 Upgrade | ||
1888 | + | ||
1889 | +1. Install Searchkick 4 | ||
1890 | +2. Upgrade your Elasticsearch cluster | ||
1891 | + | ||
1903 | ## Elasticsearch 5 to 6 Upgrade | 1892 | ## Elasticsearch 5 to 6 Upgrade |
1904 | 1893 | ||
1905 | Elasticsearch 6 removes the ability to reindex with the `_all` field. Before you upgrade, we recommend disabling this field manually and specifying default fields on your models. | 1894 | Elasticsearch 6 removes the ability to reindex with the `_all` field. Before you upgrade, we recommend disabling this field manually and specifying default fields on your models. |
lib/searchkick.rb
@@ -78,16 +78,36 @@ module Searchkick | @@ -78,16 +78,36 @@ module Searchkick | ||
78 | Gem::Version.new(server_version.split("-")[0]) < Gem::Version.new(version.split("-")[0]) | 78 | Gem::Version.new(server_version.split("-")[0]) < Gem::Version.new(version.split("-")[0]) |
79 | end | 79 | end |
80 | 80 | ||
81 | + # memoize for performance | ||
82 | + def self.server_below7? | ||
83 | + unless defined?(@server_below7) | ||
84 | + @server_below7 = server_below?("7.0.0") | ||
85 | + end | ||
86 | + @server_below7 | ||
87 | + end | ||
88 | + | ||
81 | def self.search(term = "*", model: nil, **options, &block) | 89 | def self.search(term = "*", model: nil, **options, &block) |
82 | options = options.dup | 90 | options = options.dup |
83 | klass = model | 91 | klass = model |
84 | 92 | ||
85 | - # make Searchkick.search(index_name: [Product]) and Product.search equivalent | 93 | + # convert index_name into models if possible |
94 | + # this should allow for easier upgrade | ||
95 | + if options[:index_name] && !options[:models] && Array(options[:index_name]).all? { |v| v.respond_to?(:searchkick_index) } | ||
96 | + options[:models] = options.delete(:index_name) | ||
97 | + end | ||
98 | + | ||
99 | + # make Searchkick.search(models: [Product]) and Product.search equivalent | ||
86 | unless klass | 100 | unless klass |
87 | - index_name = Array(options[:index_name]) | ||
88 | - if index_name.size == 1 && index_name.first.respond_to?(:searchkick_index) | ||
89 | - klass = index_name.first | ||
90 | - options.delete(:index_name) | 101 | + models = Array(options[:models]) |
102 | + if models.size == 1 | ||
103 | + klass = models.first | ||
104 | + options.delete(:models) | ||
105 | + end | ||
106 | + end | ||
107 | + | ||
108 | + if klass | ||
109 | + if (options[:models] && Array(options[:models]) != [klass]) || Array(options[:index_name]).any? { |v| v.respond_to?(:searchkick_index) && v != klass } | ||
110 | + raise ArgumentError, "Use Searchkick.search to search multiple models" | ||
91 | end | 111 | end |
92 | end | 112 | end |
93 | 113 |
lib/searchkick/index.rb
@@ -17,7 +17,7 @@ module Searchkick | @@ -17,7 +17,7 @@ module Searchkick | ||
17 | end | 17 | end |
18 | 18 | ||
19 | def delete | 19 | def delete |
20 | - if !Searchkick.server_below?("6.0.0") && alias_exists? | 20 | + if alias_exists? |
21 | # can't call delete directly on aliases in ES 6 | 21 | # can't call delete directly on aliases in ES 6 |
22 | indices = client.indices.get_alias(name: name).keys | 22 | indices = client.indices.get_alias(name: name).keys |
23 | client.indices.delete index: indices | 23 | client.indices.delete index: indices |
@@ -68,7 +68,7 @@ module Searchkick | @@ -68,7 +68,7 @@ module Searchkick | ||
68 | } | 68 | } |
69 | ) | 69 | ) |
70 | 70 | ||
71 | - response["hits"]["total"] | 71 | + Searchkick::Results.new(nil, response).total_count |
72 | end | 72 | end |
73 | 73 | ||
74 | def promote(new_name, update_refresh_interval: false) | 74 | def promote(new_name, update_refresh_interval: false) |
lib/searchkick/index_options.rb
@@ -4,15 +4,13 @@ module Searchkick | @@ -4,15 +4,13 @@ module Searchkick | ||
4 | options = @options | 4 | options = @options |
5 | language = options[:language] | 5 | language = options[:language] |
6 | language = language.call if language.respond_to?(:call) | 6 | language = language.call if language.respond_to?(:call) |
7 | - index_type = options[:_type] | ||
8 | - index_type = index_type.call if index_type.respond_to?(:call) | ||
9 | 7 | ||
10 | if options[:mappings] && !options[:merge_mappings] | 8 | if options[:mappings] && !options[:merge_mappings] |
11 | settings = options[:settings] || {} | 9 | settings = options[:settings] || {} |
12 | mappings = options[:mappings] | 10 | mappings = options[:mappings] |
13 | else | 11 | else |
14 | - below60 = Searchkick.server_below?("6.0.0") | ||
15 | below62 = Searchkick.server_below?("6.2.0") | 12 | below62 = Searchkick.server_below?("6.2.0") |
13 | + below70 = Searchkick.server_below?("7.0.0") | ||
16 | 14 | ||
17 | default_type = "text" | 15 | default_type = "text" |
18 | default_analyzer = :searchkick_index | 16 | default_analyzer = :searchkick_index |
@@ -144,15 +142,6 @@ module Searchkick | @@ -144,15 +142,6 @@ module Searchkick | ||
144 | } | 142 | } |
145 | } | 143 | } |
146 | 144 | ||
147 | - if below60 | ||
148 | - # ES docs say standard token filter does nothing in ES 5 | ||
149 | - # (and therefore isn't needed at at), but tests say otherwise | ||
150 | - # https://www.elastic.co/guide/en/elasticsearch/reference/5.0/analysis-standard-tokenfilter.html | ||
151 | - [default_analyzer, :searchkick_search, :searchkick_search2].each do |analyzer| | ||
152 | - settings[:analysis][:analyzer][analyzer][:filter].unshift("standard") | ||
153 | - end | ||
154 | - end | ||
155 | - | ||
156 | stem = options[:stem] | 145 | stem = options[:stem] |
157 | 146 | ||
158 | case language | 147 | case language |
@@ -279,8 +268,7 @@ module Searchkick | @@ -279,8 +268,7 @@ module Searchkick | ||
279 | # - Only apply the synonym expansion at index time | 268 | # - Only apply the synonym expansion at index time |
280 | # - Don't have the synonym filter applied search | 269 | # - Don't have the synonym filter applied search |
281 | # - Use directional synonyms where appropriate. You want to make sure that you're not injecting terms that are too general. | 270 | # - Use directional synonyms where appropriate. You want to make sure that you're not injecting terms that are too general. |
282 | - settings[:analysis][:analyzer][default_analyzer][:filter].insert(4, "searchkick_synonym") if below60 | ||
283 | - settings[:analysis][:analyzer][default_analyzer][:filter] << "searchkick_synonym" | 271 | + settings[:analysis][:analyzer][default_analyzer][:filter].insert(2, "searchkick_synonym") |
284 | 272 | ||
285 | %w(word_start word_middle word_end).each do |type| | 273 | %w(word_start word_middle word_end).each do |type| |
286 | settings[:analysis][:analyzer]["searchkick_#{type}_index".to_sym][:filter].insert(2, "searchkick_synonym") | 274 | settings[:analysis][:analyzer]["searchkick_#{type}_index".to_sym][:filter].insert(2, "searchkick_synonym") |
@@ -391,10 +379,6 @@ module Searchkick | @@ -391,10 +379,6 @@ module Searchkick | ||
391 | "{name}" => keyword_mapping | 379 | "{name}" => keyword_mapping |
392 | } | 380 | } |
393 | 381 | ||
394 | - if below60 && all | ||
395 | - dynamic_fields["{name}"][:include_in_all] = !options[:searchable] | ||
396 | - end | ||
397 | - | ||
398 | if options.key?(:filterable) | 382 | if options.key?(:filterable) |
399 | dynamic_fields["{name}"] = {type: default_type, index: index_false_value} | 383 | dynamic_fields["{name}"] = {type: default_type, index: index_false_value} |
400 | end | 384 | end |
@@ -413,25 +397,24 @@ module Searchkick | @@ -413,25 +397,24 @@ module Searchkick | ||
413 | multi_field = dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}")) | 397 | multi_field = dynamic_fields["{name}"].merge(fields: dynamic_fields.except("{name}")) |
414 | 398 | ||
415 | mappings = { | 399 | mappings = { |
416 | - index_type => { | ||
417 | - properties: mapping, | ||
418 | - _routing: routing, | ||
419 | - # https://gist.github.com/kimchy/2898285 | ||
420 | - dynamic_templates: [ | ||
421 | - { | ||
422 | - string_template: { | ||
423 | - match: "*", | ||
424 | - match_mapping_type: "string", | ||
425 | - mapping: multi_field | ||
426 | - } | 400 | + properties: mapping, |
401 | + _routing: routing, | ||
402 | + # https://gist.github.com/kimchy/2898285 | ||
403 | + dynamic_templates: [ | ||
404 | + { | ||
405 | + string_template: { | ||
406 | + match: "*", | ||
407 | + match_mapping_type: "string", | ||
408 | + mapping: multi_field | ||
427 | } | 409 | } |
428 | - ] | ||
429 | - } | 410 | + } |
411 | + ] | ||
430 | } | 412 | } |
431 | 413 | ||
432 | - if below60 | ||
433 | - all_enabled = all && (!options[:searchable] || options[:searchable].to_a.map(&:to_s).include?("_all")) | ||
434 | - mappings[index_type][:_all] = all_enabled ? analyzed_field_options : {enabled: false} | 414 | + if below70 |
415 | + index_type = options[:_type] | ||
416 | + index_type = index_type.call if index_type.respond_to?(:call) | ||
417 | + mappings = {index_type => mappings} | ||
435 | end | 418 | end |
436 | 419 | ||
437 | mappings = mappings.symbolize_keys.deep_merge((options[:mappings] || {}).symbolize_keys) | 420 | mappings = mappings.symbolize_keys.deep_merge((options[:mappings] || {}).symbolize_keys) |
lib/searchkick/query.rb
@@ -18,7 +18,7 @@ module Searchkick | @@ -18,7 +18,7 @@ module Searchkick | ||
18 | unknown_keywords = options.keys - [:aggs, :block, :body, :body_options, :boost, | 18 | unknown_keywords = options.keys - [:aggs, :block, :body, :body_options, :boost, |
19 | :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain, | 19 | :boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :execute, :explain, |
20 | :fields, :highlight, :includes, :index_name, :indices_boost, :limit, :load, | 20 | :fields, :highlight, :includes, :index_name, :indices_boost, :limit, :load, |
21 | - :match, :misspellings, :model_includes, :offset, :operator, :order, :padding, :page, :per_page, :profile, | 21 | + :match, :misspellings, :models, :model_includes, :offset, :operator, :order, :padding, :page, :per_page, :profile, |
22 | :request_params, :routing, :scope_results, :select, :similar, :smart_aggs, :suggest, :total_entries, :track, :type, :where] | 22 | :request_params, :routing, :scope_results, :select, :similar, :smart_aggs, :suggest, :total_entries, :track, :type, :where] |
23 | raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any? | 23 | raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any? |
24 | 24 | ||
@@ -39,6 +39,7 @@ module Searchkick | @@ -39,6 +39,7 @@ module Searchkick | ||
39 | @misspellings = false | 39 | @misspellings = false |
40 | @misspellings_below = nil | 40 | @misspellings_below = nil |
41 | @highlighted_fields = nil | 41 | @highlighted_fields = nil |
42 | + @index_mapping = nil | ||
42 | 43 | ||
43 | prepare | 44 | prepare |
44 | end | 45 | end |
@@ -56,9 +57,18 @@ module Searchkick | @@ -56,9 +57,18 @@ module Searchkick | ||
56 | end | 57 | end |
57 | 58 | ||
58 | def params | 59 | def params |
60 | + if options[:models] | ||
61 | + @index_mapping = {} | ||
62 | + Array(options[:models]).each do |model| | ||
63 | + @index_mapping[model.searchkick_index.name] = model | ||
64 | + end | ||
65 | + end | ||
66 | + | ||
59 | index = | 67 | index = |
60 | if options[:index_name] | 68 | if options[:index_name] |
61 | Array(options[:index_name]).map { |v| v.respond_to?(:searchkick_index) ? v.searchkick_index.name : v }.join(",") | 69 | Array(options[:index_name]).map { |v| v.respond_to?(:searchkick_index) ? v.searchkick_index.name : v }.join(",") |
70 | + elsif options[:models] | ||
71 | + @index_mapping.keys.join(",") | ||
62 | elsif searchkick_index | 72 | elsif searchkick_index |
63 | searchkick_index.name | 73 | searchkick_index.name |
64 | else | 74 | else |
@@ -116,8 +126,8 @@ module Searchkick | @@ -116,8 +126,8 @@ module Searchkick | ||
116 | misspellings: @misspellings, | 126 | misspellings: @misspellings, |
117 | term: term, | 127 | term: term, |
118 | scope_results: options[:scope_results], | 128 | scope_results: options[:scope_results], |
119 | - index_name: options[:index_name], | ||
120 | - total_entries: options[:total_entries] | 129 | + total_entries: options[:total_entries], |
130 | + index_mapping: @index_mapping | ||
121 | } | 131 | } |
122 | 132 | ||
123 | if options[:debug] | 133 | if options[:debug] |
@@ -166,7 +176,7 @@ module Searchkick | @@ -166,7 +176,7 @@ module Searchkick | ||
166 | end | 176 | end |
167 | 177 | ||
168 | def retry_misspellings?(response) | 178 | def retry_misspellings?(response) |
169 | - @misspellings_below && response["hits"]["total"] < @misspellings_below | 179 | + @misspellings_below && Searchkick::Results.new(searchkick_klass, response).total_count < @misspellings_below |
170 | end | 180 | end |
171 | 181 | ||
172 | private | 182 | private |
@@ -377,7 +387,7 @@ module Searchkick | @@ -377,7 +387,7 @@ module Searchkick | ||
377 | queries_to_add.concat(q2) | 387 | queries_to_add.concat(q2) |
378 | end | 388 | end |
379 | 389 | ||
380 | - queries.concat(queries_to_add) | 390 | + queries << queries_to_add |
381 | 391 | ||
382 | if options[:exclude] | 392 | if options[:exclude] |
383 | must_not.concat(set_exclude(exclude_field, exclude_analyzer)) | 393 | must_not.concat(set_exclude(exclude_field, exclude_analyzer)) |
@@ -392,9 +402,10 @@ module Searchkick | @@ -392,9 +402,10 @@ module Searchkick | ||
392 | 402 | ||
393 | should = [] | 403 | should = [] |
394 | else | 404 | else |
405 | + # higher score for matching more fields | ||
395 | payload = { | 406 | payload = { |
396 | - dis_max: { | ||
397 | - queries: queries | 407 | + bool: { |
408 | + should: queries.map { |qs| {dis_max: {queries: qs}} } | ||
398 | } | 409 | } |
399 | } | 410 | } |
400 | 411 | ||
@@ -663,20 +674,9 @@ module Searchkick | @@ -663,20 +674,9 @@ module Searchkick | ||
663 | def set_boost_by_indices(payload) | 674 | def set_boost_by_indices(payload) |
664 | return unless options[:indices_boost] | 675 | return unless options[:indices_boost] |
665 | 676 | ||
666 | - if below52? | ||
667 | - indices_boost = options[:indices_boost].each_with_object({}) do |(key, boost), memo| | ||
668 | - index = key.respond_to?(:searchkick_index) ? key.searchkick_index.name : key | ||
669 | - # try to use index explicitly instead of alias: https://github.com/elasticsearch/elasticsearch/issues/4756 | ||
670 | - index_by_alias = Searchkick.client.indices.get_alias(index: index).keys.first | ||
671 | - memo[index_by_alias || index] = boost | ||
672 | - end | ||
673 | - else | ||
674 | - # array format supports alias resolution | ||
675 | - # https://github.com/elastic/elasticsearch/pull/21393 | ||
676 | - indices_boost = options[:indices_boost].map do |key, boost| | ||
677 | - index = key.respond_to?(:searchkick_index) ? key.searchkick_index.name : key | ||
678 | - {index => boost} | ||
679 | - end | 677 | + indices_boost = options[:indices_boost].map do |key, boost| |
678 | + index = key.respond_to?(:searchkick_index) ? key.searchkick_index.name : key | ||
679 | + {index => boost} | ||
680 | end | 680 | end |
681 | 681 | ||
682 | payload[:indices_boost] = indices_boost | 682 | payload[:indices_boost] = indices_boost |
@@ -713,7 +713,7 @@ module Searchkick | @@ -713,7 +713,7 @@ module Searchkick | ||
713 | def set_highlights(payload, fields) | 713 | def set_highlights(payload, fields) |
714 | payload[:highlight] = { | 714 | payload[:highlight] = { |
715 | fields: Hash[fields.map { |f| [f, {}] }], | 715 | fields: Hash[fields.map { |f| [f, {}] }], |
716 | - fragment_size: below60? ? 30000 : 0 | 716 | + fragment_size: 0 |
717 | } | 717 | } |
718 | 718 | ||
719 | if options[:highlight].is_a?(Hash) | 719 | if options[:highlight].is_a?(Hash) |
@@ -824,7 +824,7 @@ module Searchkick | @@ -824,7 +824,7 @@ module Searchkick | ||
824 | # TODO id transformation for arrays | 824 | # TODO id transformation for arrays |
825 | def set_order(payload) | 825 | def set_order(payload) |
826 | order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc} | 826 | order = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc} |
827 | - id_field = below60? ? :_uid : :_id | 827 | + id_field = :_id |
828 | payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? id_field : k, v] }] | 828 | payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? id_field : k, v] }] |
829 | end | 829 | end |
830 | 830 | ||
@@ -1021,16 +1021,12 @@ module Searchkick | @@ -1021,16 +1021,12 @@ module Searchkick | ||
1021 | k.sub(/\.(analyzed|word_start|word_middle|word_end|text_start|text_middle|text_end|exact)\z/, "") | 1021 | k.sub(/\.(analyzed|word_start|word_middle|word_end|text_start|text_middle|text_end|exact)\z/, "") |
1022 | end | 1022 | end |
1023 | 1023 | ||
1024 | - def below52? | ||
1025 | - Searchkick.server_below?("5.2.0") | ||
1026 | - end | ||
1027 | - | ||
1028 | - def below60? | ||
1029 | - Searchkick.server_below?("6.0.0") | ||
1030 | - end | ||
1031 | - | ||
1032 | def below61? | 1024 | def below61? |
1033 | Searchkick.server_below?("6.1.0") | 1025 | Searchkick.server_below?("6.1.0") |
1034 | end | 1026 | end |
1027 | + | ||
1028 | + def below70? | ||
1029 | + Searchkick.server_below?("7.0.0") | ||
1030 | + end | ||
1035 | end | 1031 | end |
1036 | end | 1032 | end |
lib/searchkick/record_data.rb
@@ -34,18 +34,13 @@ module Searchkick | @@ -34,18 +34,13 @@ module Searchkick | ||
34 | index.klass_document_type(record.class, ignore_type) | 34 | index.klass_document_type(record.class, ignore_type) |
35 | end | 35 | end |
36 | 36 | ||
37 | - # memoize | ||
38 | - def self.routing_key | ||
39 | - @routing_key ||= Searchkick.server_below?("6.0.0") ? :_routing : :routing | ||
40 | - end | ||
41 | - | ||
42 | def record_data | 37 | def record_data |
43 | data = { | 38 | data = { |
44 | _index: index.name, | 39 | _index: index.name, |
45 | - _id: search_id, | ||
46 | - _type: document_type | 40 | + _id: search_id |
47 | } | 41 | } |
48 | - data[self.class.routing_key] = record.search_routing if record.respond_to?(:search_routing) | 42 | + data[:_type] = document_type if Searchkick.server_below7? |
43 | + data[:routing] = record.search_routing if record.respond_to?(:search_routing) | ||
49 | data | 44 | data |
50 | end | 45 | end |
51 | 46 |
lib/searchkick/results.rb
@@ -25,9 +25,16 @@ module Searchkick | @@ -25,9 +25,16 @@ module Searchkick | ||
25 | # results can have different types | 25 | # results can have different types |
26 | results = {} | 26 | results = {} |
27 | 27 | ||
28 | - hits.group_by { |hit, _| hit["_type"] }.each do |type, grouped_hits| | ||
29 | - klass = (!options[:index_name] && @klass) || type.camelize.constantize | ||
30 | - results[type] = results_query(klass, grouped_hits).to_a.index_by { |r| r.id.to_s } | 28 | + hits.group_by { |hit, _| hit["_index"] }.each do |index, grouped_hits| |
29 | + klass = | ||
30 | + if @klass | ||
31 | + @klass | ||
32 | + else | ||
33 | + index_alias = index.split("_")[0..-2].join("_") | ||
34 | + (options[:index_mapping] || {})[index_alias] | ||
35 | + end | ||
36 | + raise Searchkick::Error, "Unknown model for index: #{index}" unless klass | ||
37 | + results[index] = results_query(klass, grouped_hits).to_a.index_by { |r| r.id.to_s } | ||
31 | end | 38 | end |
32 | 39 | ||
33 | missing_ids = [] | 40 | missing_ids = [] |
@@ -35,7 +42,7 @@ module Searchkick | @@ -35,7 +42,7 @@ module Searchkick | ||
35 | # sort | 42 | # sort |
36 | results = | 43 | results = |
37 | hits.map do |hit| | 44 | hits.map do |hit| |
38 | - result = results[hit["_type"]][hit["_id"].to_s] | 45 | + result = results[hit["_index"]][hit["_id"].to_s] |
39 | if result && !(options[:load].is_a?(Hash) && options[:load][:dumpable]) | 46 | if result && !(options[:load].is_a?(Hash) && options[:load][:dumpable]) |
40 | if (hit["highlight"] || options[:highlight]) && !result.respond_to?(:search_highlights) | 47 | if (hit["highlight"] || options[:highlight]) && !result.respond_to?(:search_highlights) |
41 | highlights = hit_highlights(hit) | 48 | highlights = hit_highlights(hit) |
@@ -132,7 +139,13 @@ module Searchkick | @@ -132,7 +139,13 @@ module Searchkick | ||
132 | end | 139 | end |
133 | 140 | ||
134 | def total_count | 141 | def total_count |
135 | - options[:total_entries] || response["hits"]["total"] | 142 | + if options[:total_entries] |
143 | + options[:total_entries] | ||
144 | + elsif response["hits"]["total"].is_a?(Hash) | ||
145 | + response["hits"]["total"]["value"] | ||
146 | + else | ||
147 | + response["hits"]["total"] | ||
148 | + end | ||
136 | end | 149 | end |
137 | alias_method :total_entries, :total_count | 150 | alias_method :total_entries, :total_count |
138 | 151 |
searchkick.gemspec
@@ -16,10 +16,10 @@ Gem::Specification.new do |spec| | @@ -16,10 +16,10 @@ Gem::Specification.new do |spec| | ||
16 | spec.files = Dir["*.{md,txt}", "{lib}/**/*"] | 16 | spec.files = Dir["*.{md,txt}", "{lib}/**/*"] |
17 | spec.require_path = "lib" | 17 | spec.require_path = "lib" |
18 | 18 | ||
19 | - spec.required_ruby_version = ">= 2.2" | 19 | + spec.required_ruby_version = ">= 2.4" |
20 | 20 | ||
21 | - spec.add_dependency "activemodel", ">= 4.2" | ||
22 | - spec.add_dependency "elasticsearch", ">= 5" | 21 | + spec.add_dependency "activemodel", ">= 5" |
22 | + spec.add_dependency "elasticsearch", ">= 6" | ||
23 | spec.add_dependency "hashie" | 23 | spec.add_dependency "hashie" |
24 | 24 | ||
25 | spec.add_development_dependency "bundler" | 25 | spec.add_development_dependency "bundler" |
test/aggs_test.rb
@@ -20,8 +20,7 @@ class AggsTest < Minitest::Test | @@ -20,8 +20,7 @@ class AggsTest < Minitest::Test | ||
20 | end | 20 | end |
21 | 21 | ||
22 | def test_order | 22 | def test_order |
23 | - order_key = Searchkick.server_below?("6.0") ? "_term" : "_key" | ||
24 | - agg = Product.search("Product", aggs: {color: {order: {order_key => "desc"}}}).aggs["color"] | 23 | + agg = Product.search("Product", aggs: {color: {order: {_key: "desc"}}}).aggs["color"] |
25 | assert_equal %w(red green blue), agg["buckets"].map { |b| b["key"] } | 24 | assert_equal %w(red green blue), agg["buckets"].map { |b| b["key"] } |
26 | end | 25 | end |
27 | 26 | ||
@@ -37,8 +36,7 @@ class AggsTest < Minitest::Test | @@ -37,8 +36,7 @@ class AggsTest < Minitest::Test | ||
37 | 36 | ||
38 | def test_script | 37 | def test_script |
39 | source = "'Color: ' + _value" | 38 | source = "'Color: ' + _value" |
40 | - script = Searchkick.server_below?("5.6") ? {inline: source} : {source: source} | ||
41 | - agg = Product.search("Product", aggs: {color: {script: script}}).aggs["color"] | 39 | + agg = Product.search("Product", aggs: {color: {script: {source: source}}}).aggs["color"] |
42 | assert_equal ({"Color: blue" => 1, "Color: green" => 1, "Color: red" => 1}), buckets_as_hash(agg) | 40 | assert_equal ({"Color: blue" => 1, "Color: green" => 1, "Color: red" => 1}), buckets_as_hash(agg) |
43 | end | 41 | end |
44 | 42 |
test/boost_test.rb
@@ -67,6 +67,7 @@ class BoostTest < Minitest::Test | @@ -67,6 +67,7 @@ class BoostTest < Minitest::Test | ||
67 | end | 67 | end |
68 | 68 | ||
69 | def test_conversions_weight | 69 | def test_conversions_weight |
70 | + Product.reindex | ||
70 | store [ | 71 | store [ |
71 | {name: "Product Boost", orders_count: 20}, | 72 | {name: "Product Boost", orders_count: 20}, |
72 | {name: "Product Conversions", conversions: {"product" => 10}} | 73 | {name: "Product Conversions", conversions: {"product" => 10}} |
@@ -229,6 +230,6 @@ class BoostTest < Minitest::Test | @@ -229,6 +230,6 @@ class BoostTest < Minitest::Test | ||
229 | store_names ["Rex"], Animal | 230 | store_names ["Rex"], Animal |
230 | store_names ["Rexx"], Product | 231 | store_names ["Rexx"], Product |
231 | 232 | ||
232 | - assert_order "Rex", ["Rexx", "Rex"], {index_name: [Animal, Product], indices_boost: {Animal => 1, Product => 200}, fields: [:name]}, Store | 233 | + assert_order "Rex", ["Rexx", "Rex"], {models: [Animal, Product], indices_boost: {Animal => 1, Product => 200}, fields: [:name]}, Searchkick |
233 | end | 234 | end |
234 | end | 235 | end |
test/ci/install_elasticsearch.sh
@@ -5,15 +5,13 @@ set -e | @@ -5,15 +5,13 @@ set -e | ||
5 | CACHE_DIR=$HOME/elasticsearch/$ELASTICSEARCH_VERSION | 5 | CACHE_DIR=$HOME/elasticsearch/$ELASTICSEARCH_VERSION |
6 | 6 | ||
7 | if [ ! -d "$CACHE_DIR" ]; then | 7 | if [ ! -d "$CACHE_DIR" ]; then |
8 | - if [[ $ELASTICSEARCH_VERSION == 1* ]]; then | ||
9 | - URL=https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-$ELASTICSEARCH_VERSION.tar.gz | ||
10 | - elif [[ $ELASTICSEARCH_VERSION == 2* ]]; then | ||
11 | - URL=https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/$ELASTICSEARCH_VERSION/elasticsearch-$ELASTICSEARCH_VERSION.tar.gz | 8 | + if [[ $ELASTICSEARCH_VERSION == 7* ]]; then |
9 | + URL=https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-$ELASTICSEARCH_VERSION-linux-x86_64.tar.gz | ||
12 | else | 10 | else |
13 | URL=https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-$ELASTICSEARCH_VERSION.tar.gz | 11 | URL=https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-$ELASTICSEARCH_VERSION.tar.gz |
14 | fi | 12 | fi |
15 | 13 | ||
16 | - wget $URL | 14 | + wget -O elasticsearch-$ELASTICSEARCH_VERSION.tar.gz $URL |
17 | tar xvfz elasticsearch-$ELASTICSEARCH_VERSION.tar.gz | 15 | tar xvfz elasticsearch-$ELASTICSEARCH_VERSION.tar.gz |
18 | mv elasticsearch-$ELASTICSEARCH_VERSION $CACHE_DIR | 16 | mv elasticsearch-$ELASTICSEARCH_VERSION $CACHE_DIR |
19 | else | 17 | else |
test/errors_test.rb
@@ -4,13 +4,15 @@ class ErrorsTest < Minitest::Test | @@ -4,13 +4,15 @@ class ErrorsTest < Minitest::Test | ||
4 | def test_bulk_import_raises_error | 4 | def test_bulk_import_raises_error |
5 | valid_dog = Product.create(name: "2016-01-02") | 5 | valid_dog = Product.create(name: "2016-01-02") |
6 | invalid_dog = Product.create(name: "Ol' One-Leg") | 6 | invalid_dog = Product.create(name: "Ol' One-Leg") |
7 | - index = Searchkick::Index.new "dogs", mappings: { | ||
8 | - dog: { | ||
9 | - properties: { | ||
10 | - name: {type: "date"} | ||
11 | - } | 7 | + mapping = { |
8 | + properties: { | ||
9 | + name: {type: "date"} | ||
12 | } | 10 | } |
13 | } | 11 | } |
12 | + mapping = {product: mapping} if Searchkick.server_below?("7.0.0") | ||
13 | + index = Searchkick::Index.new "dogs", mappings: mapping | ||
14 | + index.delete if index.exists? | ||
15 | + index.create_index | ||
14 | index.store valid_dog | 16 | index.store valid_dog |
15 | assert_raises(Searchkick::ImportError) do | 17 | assert_raises(Searchkick::ImportError) do |
16 | index.bulk_index [valid_dog, invalid_dog] | 18 | index.bulk_index [valid_dog, invalid_dog] |
test/gemfiles/activerecord42.gemfile
test/gemfiles/mongoid5.gemfile
test/geo_shape_test.rb
@@ -32,6 +32,9 @@ class GeoShapeTest < Minitest::Test | @@ -32,6 +32,9 @@ class GeoShapeTest < Minitest::Test | ||
32 | end | 32 | end |
33 | 33 | ||
34 | def test_circle | 34 | def test_circle |
35 | + # https://github.com/elastic/elasticsearch/issues/39237 | ||
36 | + skip unless Searchkick.server_below?("6.6.0") | ||
37 | + | ||
35 | assert_search "*", ["Region A"], { | 38 | assert_search "*", ["Region A"], { |
36 | where: { | 39 | where: { |
37 | territory: { | 40 | territory: { |
@@ -142,6 +145,9 @@ class GeoShapeTest < Minitest::Test | @@ -142,6 +145,9 @@ class GeoShapeTest < Minitest::Test | ||
142 | end | 145 | end |
143 | 146 | ||
144 | def test_contains | 147 | def test_contains |
148 | + # CONTAINS query relation not supported | ||
149 | + skip unless Searchkick.server_below?("6.6.0") | ||
150 | + | ||
145 | assert_search "*", ["Region C"], { | 151 | assert_search "*", ["Region C"], { |
146 | where: { | 152 | where: { |
147 | territory: { | 153 | territory: { |
test/inheritance_test.rb
@@ -77,6 +77,20 @@ class InheritanceTest < Minitest::Test | @@ -77,6 +77,20 @@ class InheritanceTest < Minitest::Test | ||
77 | def test_multiple_indices | 77 | def test_multiple_indices |
78 | store_names ["Product A"] | 78 | store_names ["Product A"] |
79 | store_names ["Product B"], Animal | 79 | store_names ["Product B"], Animal |
80 | - assert_search "product", ["Product A", "Product B"], index_name: [Product.searchkick_index.name, Animal.searchkick_index.name], conversions: false | 80 | + assert_search "product", ["Product A", "Product B"], {models: [Product, Animal], conversions: false}, Searchkick |
81 | + assert_search "product", ["Product A", "Product B"], {index_name: [Product, Animal], conversions: false}, Searchkick | ||
82 | + end | ||
83 | + | ||
84 | + def test_index_name_model | ||
85 | + store_names ["Product A"] | ||
86 | + assert_equal ["Product A"], Searchkick.search("product", index_name: [Product]).map(&:name) | ||
87 | + end | ||
88 | + | ||
89 | + def test_index_name_string | ||
90 | + store_names ["Product A"] | ||
91 | + error = assert_raises Searchkick::Error do | ||
92 | + Searchkick.search("product", index_name: [Product.searchkick_index.name]).map(&:name) | ||
93 | + end | ||
94 | + assert_includes error.message, "Unknown model" | ||
81 | end | 95 | end |
82 | end | 96 | end |
test/models/product.rb
@@ -2,11 +2,8 @@ class Product | @@ -2,11 +2,8 @@ class Product | ||
2 | searchkick \ | 2 | searchkick \ |
3 | synonyms: [ | 3 | synonyms: [ |
4 | ["clorox", "bleach"], | 4 | ["clorox", "bleach"], |
5 | - ["scallion", "greenonion"], | ||
6 | - ["saran wrap", "plastic wrap"], | ||
7 | - ["qtip", "cottonswab"], | ||
8 | ["burger", "hamburger"], | 5 | ["burger", "hamburger"], |
9 | - ["bandaid", "bandag"], | 6 | + ["bandaid", "bandages"], |
10 | ["UPPERCASE", "lowercase"], | 7 | ["UPPERCASE", "lowercase"], |
11 | "lightbulb => led,lightbulb", | 8 | "lightbulb => led,lightbulb", |
12 | "lightbulb => halogenlamp" | 9 | "lightbulb => halogenlamp" |
test/models/region.rb
test/models/store.rb
1 | class Store | 1 | class Store |
2 | + mappings = { | ||
3 | + properties: { | ||
4 | + name: {type: "keyword"} | ||
5 | + } | ||
6 | + } | ||
7 | + mappings = {store: mappings} if Searchkick.server_below?("7.0.0") | ||
8 | + | ||
2 | searchkick \ | 9 | searchkick \ |
3 | routing: true, | 10 | routing: true, |
4 | merge_mappings: true, | 11 | merge_mappings: true, |
5 | - mappings: { | ||
6 | - store: { | ||
7 | - properties: { | ||
8 | - name: {type: "keyword"} | ||
9 | - } | ||
10 | - } | ||
11 | - } | 12 | + mappings: mappings |
12 | 13 | ||
13 | def search_document_id | 14 | def search_document_id |
14 | id | 15 | id |
test/multi_indices_test.rb
@@ -7,16 +7,44 @@ class MultiIndicesTest < Minitest::Test | @@ -7,16 +7,44 @@ class MultiIndicesTest < Minitest::Test | ||
7 | assert_search_multi "product", ["Product A", "Product B"] | 7 | assert_search_multi "product", ["Product A", "Product B"] |
8 | end | 8 | end |
9 | 9 | ||
10 | - def test_where | ||
11 | - store [{name: "Product A", color: "red"}, {name: "Product B", color: "blue"}] | ||
12 | - store_names ["Product C"], Speaker | ||
13 | - assert_search_multi "product", ["Product A", "Product C"], where: {_or: [{_type: "product", color: "red"}, {_type: "speaker"}]} | 10 | + def test_index_name |
11 | + store_names ["Product A"] | ||
12 | + assert_equal ["Product A"], Product.search("product", index_name: Product.searchkick_index.name).map(&:name) | ||
13 | + assert_equal ["Product A"], Product.search("product", index_name: Product).map(&:name) | ||
14 | + assert_equal [], Product.search("product", index_name: Speaker.searchkick_index.name, conversions: false).map(&:name) | ||
15 | + end | ||
16 | + | ||
17 | + def test_models_and_index_name | ||
18 | + store_names ["Product A"] | ||
19 | + store_names ["Product B"], Speaker | ||
20 | + assert_equal ["Product A"], Searchkick.search("product", models: [Product, Store], index_name: Product.searchkick_index.name).map(&:name) | ||
21 | + error = assert_raises(Searchkick::Error) do | ||
22 | + Searchkick.search("product", models: [Product, Store], index_name: Speaker.searchkick_index.name).map(&:name) | ||
23 | + end | ||
24 | + assert_includes error.message, "Unknown model" | ||
25 | + # legacy | ||
26 | + assert_equal ["Product A"], Searchkick.search("product", index_name: [Product, Store]).map(&:name) | ||
27 | + end | ||
28 | + | ||
29 | + def test_model_with_another_model | ||
30 | + error = assert_raises(ArgumentError) do | ||
31 | + Product.search(models: [Store]) | ||
32 | + end | ||
33 | + assert_includes error.message, "Use Searchkick.search" | ||
34 | + end | ||
35 | + | ||
36 | + def test_model_with_another_model_in_index_name | ||
37 | + error = assert_raises(ArgumentError) do | ||
38 | + # legacy protection | ||
39 | + Product.search(index_name: [Store, "another"]) | ||
40 | + end | ||
41 | + assert_includes error.message, "Use Searchkick.search" | ||
14 | end | 42 | end |
15 | 43 | ||
16 | private | 44 | private |
17 | 45 | ||
18 | def assert_search_multi(term, expected, options = {}) | 46 | def assert_search_multi(term, expected, options = {}) |
19 | - options[:index_name] = [Product, Speaker] | 47 | + options[:models] = [Product, Speaker] |
20 | options[:fields] = [:name] | 48 | options[:fields] = [:name] |
21 | assert_search(term, expected, options, Searchkick) | 49 | assert_search(term, expected, options, Searchkick) |
22 | end | 50 | end |
test/query_test.rb
@@ -4,18 +4,11 @@ class QueryTest < Minitest::Test | @@ -4,18 +4,11 @@ class QueryTest < Minitest::Test | ||
4 | def test_basic | 4 | def test_basic |
5 | store_names ["Milk", "Apple"] | 5 | store_names ["Milk", "Apple"] |
6 | query = Product.search("milk", execute: false) | 6 | query = Product.search("milk", execute: false) |
7 | - # query.body = {query: {match_all: {}}} | ||
8 | - # query.body = {query: {match: {name: "Apple"}}} | ||
9 | query.body[:query] = {match_all: {}} | 7 | query.body[:query] = {match_all: {}} |
10 | assert_equal ["Apple", "Milk"], query.map(&:name).sort | 8 | assert_equal ["Apple", "Milk"], query.map(&:name).sort |
11 | assert_equal ["Apple", "Milk"], query.execute.map(&:name).sort | 9 | assert_equal ["Apple", "Milk"], query.execute.map(&:name).sort |
12 | end | 10 | end |
13 | 11 | ||
14 | - def test_with_effective_min_score | ||
15 | - store_names ["Milk", "Milk2"] | ||
16 | - assert_search "milk", ["Milk"], body_options: {min_score: 1} | ||
17 | - end | ||
18 | - | ||
19 | def test_with_uneffective_min_score | 12 | def test_with_uneffective_min_score |
20 | store_names ["Milk", "Milk2"] | 13 | store_names ["Milk", "Milk2"] |
21 | assert_search "milk", ["Milk", "Milk2"], body_options: {min_score: 0.0001} | 14 | assert_search "milk", ["Milk", "Milk2"], body_options: {min_score: 0.0001} |
test/routing_test.rb
@@ -7,8 +7,11 @@ class RoutingTest < Minitest::Test | @@ -7,8 +7,11 @@ class RoutingTest < Minitest::Test | ||
7 | end | 7 | end |
8 | 8 | ||
9 | def test_routing_mappings | 9 | def test_routing_mappings |
10 | - index_options = Store.searchkick_index.index_options | ||
11 | - assert_equal index_options[:mappings][:store][:_routing], required: true | 10 | + mappings = Store.searchkick_index.index_options[:mappings] |
11 | + if Searchkick.server_below?("7.0.0") | ||
12 | + mappings = mappings[:store] | ||
13 | + end | ||
14 | + assert_equal mappings[:_routing], required: true | ||
12 | end | 15 | end |
13 | 16 | ||
14 | def test_routing_correct_node | 17 | def test_routing_correct_node |
test/sql_test.rb
@@ -37,6 +37,7 @@ class SqlTest < Minitest::Test | @@ -37,6 +37,7 @@ class SqlTest < Minitest::Test | ||
37 | end | 37 | end |
38 | 38 | ||
39 | def test_fields_both_match | 39 | def test_fields_both_match |
40 | + # have same score due to dismax | ||
40 | store [ | 41 | store [ |
41 | {name: "Blue A", color: "red"}, | 42 | {name: "Blue A", color: "red"}, |
42 | {name: "Blue B", color: "light blue"} | 43 | {name: "Blue B", color: "light blue"} |
@@ -172,7 +173,7 @@ class SqlTest < Minitest::Test | @@ -172,7 +173,7 @@ class SqlTest < Minitest::Test | ||
172 | store_names ["Store A"], Store | 173 | store_names ["Store A"], Store |
173 | 174 | ||
174 | associations = {Product => [:store], Store => [:products]} | 175 | associations = {Product => [:store], Store => [:products]} |
175 | - result = Searchkick.search("*", index_name: [Product, Store], model_includes: associations) | 176 | + result = Searchkick.search("*", models: [Product, Store], model_includes: associations) |
176 | 177 | ||
177 | assert_equal 2, result.length | 178 | assert_equal 2, result.length |
178 | 179 |
test/suggest_test.rb
1 | require_relative "test_helper" | 1 | require_relative "test_helper" |
2 | 2 | ||
3 | class SuggestTest < Minitest::Test | 3 | class SuggestTest < Minitest::Test |
4 | + def setup | ||
5 | + super | ||
6 | + Product.reindex | ||
7 | + end | ||
8 | + | ||
4 | def test_basic | 9 | def test_basic |
5 | store_names ["Great White Shark", "Hammerhead Shark", "Tiger Shark"] | 10 | store_names ["Great White Shark", "Hammerhead Shark", "Tiger Shark"] |
6 | assert_suggest "How Big is a Tigre Shar", "how big is a tiger shark", fields: [:name] | 11 | assert_suggest "How Big is a Tigre Shar", "how big is a tiger shark", fields: [:name] |
test/synonyms_test.rb
@@ -6,11 +6,6 @@ class SynonymsTest < Minitest::Test | @@ -6,11 +6,6 @@ class SynonymsTest < Minitest::Test | ||
6 | assert_search "clorox", ["Clorox Bleach", "Kroger Bleach"] | 6 | assert_search "clorox", ["Clorox Bleach", "Kroger Bleach"] |
7 | end | 7 | end |
8 | 8 | ||
9 | - def test_saran_wrap | ||
10 | - store_names ["Saran Wrap", "Kroger Plastic Wrap"] | ||
11 | - assert_search "saran wrap", ["Saran Wrap", "Kroger Plastic Wrap"] | ||
12 | - end | ||
13 | - | ||
14 | def test_burger_buns | 9 | def test_burger_buns |
15 | store_names ["Hamburger Buns"] | 10 | store_names ["Hamburger Buns"] |
16 | assert_search "burger buns", ["Hamburger Buns"] | 11 | assert_search "burger buns", ["Hamburger Buns"] |
@@ -21,24 +16,14 @@ class SynonymsTest < Minitest::Test | @@ -21,24 +16,14 @@ class SynonymsTest < Minitest::Test | ||
21 | assert_search "bandaids", ["Band-Aid", "Kroger 12-Pack Bandages"] | 16 | assert_search "bandaids", ["Band-Aid", "Kroger 12-Pack Bandages"] |
22 | end | 17 | end |
23 | 18 | ||
24 | - def test_qtips | ||
25 | - store_names ["Q Tips", "Kroger Cotton Swabs"] | ||
26 | - assert_search "q tips", ["Q Tips", "Kroger Cotton Swabs"] | ||
27 | - end | ||
28 | - | ||
29 | def test_reverse | 19 | def test_reverse |
30 | - store_names ["Scallions"] | ||
31 | - assert_search "green onions", ["Scallions"] | ||
32 | - end | ||
33 | - | ||
34 | - def test_exact | ||
35 | - store_names ["Green Onions", "Yellow Onions"] | ||
36 | - assert_search "scallion", ["Green Onions"] | 20 | + store_names ["Hamburger"] |
21 | + assert_search "burger", ["Hamburger"] | ||
37 | end | 22 | end |
38 | 23 | ||
39 | def test_stemmed | 24 | def test_stemmed |
40 | - store_names ["Green Onions", "Yellow Onions"] | ||
41 | - assert_search "scallions", ["Green Onions"] | 25 | + store_names ["Burger"] |
26 | + assert_search "hamburgers", ["Burger"] | ||
42 | end | 27 | end |
43 | 28 | ||
44 | def test_word_start | 29 | def test_word_start |