searchkick_bharthur 0.0.1

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.
Files changed (61) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.travis.yml +44 -0
  4. data/CHANGELOG.md +360 -0
  5. data/Gemfile +8 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +1443 -0
  8. data/Rakefile +8 -0
  9. data/lib/searchkick/index.rb +662 -0
  10. data/lib/searchkick/logging.rb +185 -0
  11. data/lib/searchkick/middleware.rb +12 -0
  12. data/lib/searchkick/model.rb +105 -0
  13. data/lib/searchkick/query.rb +845 -0
  14. data/lib/searchkick/reindex_job.rb +26 -0
  15. data/lib/searchkick/reindex_v2_job.rb +23 -0
  16. data/lib/searchkick/results.rb +211 -0
  17. data/lib/searchkick/tasks.rb +33 -0
  18. data/lib/searchkick/version.rb +3 -0
  19. data/lib/searchkick.rb +159 -0
  20. data/searchkick.gemspec +28 -0
  21. data/test/aggs_test.rb +115 -0
  22. data/test/autocomplete_test.rb +65 -0
  23. data/test/boost_test.rb +144 -0
  24. data/test/callbacks_test.rb +27 -0
  25. data/test/ci/before_install.sh +21 -0
  26. data/test/dangerous_reindex_test.rb +27 -0
  27. data/test/facets_test.rb +90 -0
  28. data/test/gemfiles/activerecord31.gemfile +7 -0
  29. data/test/gemfiles/activerecord32.gemfile +7 -0
  30. data/test/gemfiles/activerecord40.gemfile +8 -0
  31. data/test/gemfiles/activerecord41.gemfile +8 -0
  32. data/test/gemfiles/activerecord50.gemfile +7 -0
  33. data/test/gemfiles/apartment.gemfile +8 -0
  34. data/test/gemfiles/mongoid2.gemfile +7 -0
  35. data/test/gemfiles/mongoid3.gemfile +6 -0
  36. data/test/gemfiles/mongoid4.gemfile +7 -0
  37. data/test/gemfiles/mongoid5.gemfile +7 -0
  38. data/test/gemfiles/nobrainer.gemfile +6 -0
  39. data/test/highlight_test.rb +63 -0
  40. data/test/index_test.rb +120 -0
  41. data/test/inheritance_test.rb +78 -0
  42. data/test/match_test.rb +227 -0
  43. data/test/misspellings_test.rb +46 -0
  44. data/test/model_test.rb +42 -0
  45. data/test/multi_search_test.rb +22 -0
  46. data/test/multi_tenancy_test.rb +22 -0
  47. data/test/order_test.rb +44 -0
  48. data/test/pagination_test.rb +53 -0
  49. data/test/query_test.rb +13 -0
  50. data/test/records_test.rb +8 -0
  51. data/test/reindex_job_test.rb +31 -0
  52. data/test/reindex_v2_job_test.rb +32 -0
  53. data/test/routing_test.rb +13 -0
  54. data/test/should_index_test.rb +32 -0
  55. data/test/similar_test.rb +28 -0
  56. data/test/sql_test.rb +196 -0
  57. data/test/suggest_test.rb +80 -0
  58. data/test/synonyms_test.rb +54 -0
  59. data/test/test_helper.rb +361 -0
  60. data/test/where_test.rb +171 -0
  61. metadata +231 -0
@@ -0,0 +1,144 @@
1
+ require_relative "test_helper"
2
+
3
+ class BoostTest < Minitest::Test
4
+ # conversions
5
+
6
+ def test_conversions
7
+ store [
8
+ {name: "Tomato A", conversions: {"tomato" => 1}},
9
+ {name: "Tomato B", conversions: {"tomato" => 2}},
10
+ {name: "Tomato C", conversions: {"tomato" => 3}}
11
+ ]
12
+ assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"]
13
+ end
14
+
15
+ def test_conversions_stemmed
16
+ store [
17
+ {name: "Tomato A", conversions: {"tomato" => 1, "tomatos" => 1, "Tomatoes" => 1}},
18
+ {name: "Tomato B", conversions: {"tomato" => 2}}
19
+ ]
20
+ assert_order "tomato", ["Tomato A", "Tomato B"]
21
+ end
22
+
23
+ # global boost
24
+
25
+ def test_boost
26
+ store [
27
+ {name: "Tomato A"},
28
+ {name: "Tomato B", orders_count: 10},
29
+ {name: "Tomato C", orders_count: 100}
30
+ ]
31
+ assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"], boost: "orders_count"
32
+ end
33
+
34
+ def test_boost_zero
35
+ store [
36
+ {name: "Zero Boost", orders_count: 0}
37
+ ]
38
+ assert_order "zero", ["Zero Boost"], boost: "orders_count"
39
+ end
40
+
41
+ def test_conversions_weight
42
+ store [
43
+ {name: "Product Boost", orders_count: 20},
44
+ {name: "Product Conversions", conversions: {"product" => 10}}
45
+ ]
46
+ assert_order "product", ["Product Conversions", "Product Boost"], boost: "orders_count"
47
+ end
48
+
49
+ def test_user_id
50
+ store [
51
+ {name: "Tomato A"},
52
+ {name: "Tomato B", user_ids: [1, 2, 3]},
53
+ {name: "Tomato C"},
54
+ {name: "Tomato D"}
55
+ ]
56
+ assert_first "tomato", "Tomato B", user_id: 2
57
+ end
58
+
59
+ def test_personalize
60
+ store [
61
+ {name: "Tomato A"},
62
+ {name: "Tomato B", user_ids: [1, 2, 3]},
63
+ {name: "Tomato C"},
64
+ {name: "Tomato D"}
65
+ ]
66
+ assert_first "tomato", "Tomato B", personalize: {user_ids: 2}
67
+ end
68
+
69
+ def test_boost_fields
70
+ store [
71
+ {name: "Red", color: "White"},
72
+ {name: "White", color: "Red Red Red"}
73
+ ]
74
+ assert_order "red", ["Red", "White"], fields: ["name^10", "color"]
75
+ end
76
+
77
+ def test_boost_fields_decimal
78
+ store [
79
+ {name: "Red", color: "White"},
80
+ {name: "White", color: "Red Red Red"}
81
+ ]
82
+ assert_order "red", ["Red", "White"], fields: ["name^10.5", "color"]
83
+ end
84
+
85
+ def test_boost_fields_word_start
86
+ store [
87
+ {name: "Red", color: "White"},
88
+ {name: "White", color: "Red Red Red"}
89
+ ]
90
+ assert_order "red", ["Red", "White"], fields: [{"name^10" => :word_start}, "color"]
91
+ end
92
+
93
+ def test_boost_by
94
+ store [
95
+ {name: "Tomato A"},
96
+ {name: "Tomato B", orders_count: 10},
97
+ {name: "Tomato C", orders_count: 100}
98
+ ]
99
+ assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"], boost_by: [:orders_count]
100
+ assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"], boost_by: {orders_count: {factor: 10}}
101
+ end
102
+
103
+ def test_boost_by_boost_mode_multiply
104
+ store [
105
+ {name: "Tomato A", found_rate: 0.9},
106
+ {name: "Tomato B"},
107
+ {name: "Tomato C", found_rate: 0.5}
108
+ ]
109
+
110
+ assert_order "tomato", ["Tomato B", "Tomato A", "Tomato C"], boost_by: {found_rate: {boost_mode: "multiply"}}
111
+ end
112
+
113
+ def test_boost_where
114
+ store [
115
+ {name: "Tomato A"},
116
+ {name: "Tomato B", user_ids: [1, 2]},
117
+ {name: "Tomato C", user_ids: [3]}
118
+ ]
119
+ assert_first "tomato", "Tomato B", boost_where: {user_ids: 2}
120
+ assert_first "tomato", "Tomato B", boost_where: {user_ids: 1..2}
121
+ assert_first "tomato", "Tomato B", boost_where: {user_ids: [1, 4]}
122
+ assert_first "tomato", "Tomato B", boost_where: {user_ids: {value: 2, factor: 10}}
123
+ assert_first "tomato", "Tomato B", boost_where: {user_ids: {value: [1, 4], factor: 10}}
124
+ assert_order "tomato", ["Tomato C", "Tomato B", "Tomato A"], boost_where: {user_ids: [{value: 1, factor: 10}, {value: 3, factor: 20}]}
125
+ end
126
+
127
+ def test_boost_by_distance
128
+ store [
129
+ {name: "San Francisco", latitude: 37.7833, longitude: -122.4167},
130
+ {name: "San Antonio", latitude: 29.4167, longitude: -98.5000},
131
+ {name: "San Marino", latitude: 43.9333, longitude: 12.4667}
132
+ ]
133
+ assert_order "san", ["San Francisco", "San Antonio", "San Marino"], boost_by_distance: {field: :location, origin: [37, -122], scale: "1000mi"}
134
+ end
135
+
136
+ def test_boost_by_distance_hash
137
+ store [
138
+ {name: "San Francisco", latitude: 37.7833, longitude: -122.4167},
139
+ {name: "San Antonio", latitude: 29.4167, longitude: -98.5000},
140
+ {name: "San Marino", latitude: 43.9333, longitude: 12.4667}
141
+ ]
142
+ assert_order "san", ["San Francisco", "San Antonio", "San Marino"], boost_by_distance: {field: :location, origin: {lat: 37, lon: -122}, scale: "1000mi"}
143
+ end
144
+ end
@@ -0,0 +1,27 @@
1
+ require_relative "test_helper"
2
+
3
+ class CallbacksTest < Minitest::Test
4
+ def test_true_create
5
+ Searchkick.callbacks(true) do
6
+ store_names ["Product A", "Product B"]
7
+ end
8
+ Product.searchkick_index.refresh
9
+ assert_search "product", ["Product A", "Product B"]
10
+ end
11
+
12
+ def test_false_create
13
+ Searchkick.callbacks(false) do
14
+ store_names ["Product A", "Product B"]
15
+ end
16
+ Product.searchkick_index.refresh
17
+ assert_search "product", []
18
+ end
19
+
20
+ def test_bulk_create
21
+ Searchkick.callbacks(:bulk) do
22
+ store_names ["Product A", "Product B"]
23
+ end
24
+ Product.searchkick_index.refresh
25
+ assert_search "product", ["Product A", "Product B"]
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env bash
2
+
3
+ gem install bundler
4
+
5
+ sudo apt-get purge elasticsearch
6
+ if [[ $ELASTICSEARCH_VERSION == 1* ]]; then
7
+ wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-$ELASTICSEARCH_VERSION.deb
8
+ else
9
+ wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/deb/elasticsearch/$ELASTICSEARCH_VERSION/elasticsearch-$ELASTICSEARCH_VERSION.deb
10
+ fi
11
+ sudo dpkg -i elasticsearch-$ELASTICSEARCH_VERSION.deb
12
+ sudo service elasticsearch start
13
+
14
+ if [ -n "$NOBRAINER" ]; then
15
+ source /etc/lsb-release && echo "deb http://download.rethinkdb.com/apt $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list
16
+ wget -qO- http://download.rethinkdb.com/apt/pubkey.gpg | sudo apt-key add -
17
+ sudo apt-get update -q
18
+ sudo apt-get install rethinkdb
19
+ sudo cp /etc/rethinkdb/default.conf.sample /etc/rethinkdb/instances.d/instance1.conf
20
+ sudo service rethinkdb restart
21
+ fi
@@ -0,0 +1,27 @@
1
+ require_relative "test_helper"
2
+
3
+ class DangerousReindexTest < Minitest::Test
4
+ def setup
5
+ skip if mongoid2? || nobrainer? || activerecord_below41?
6
+ super
7
+ end
8
+
9
+ def test_dangerous_reindex
10
+ assert_raises(Searchkick::DangerousOperation) { Product.where(id: [1, 2, 3]).reindex }
11
+ end
12
+
13
+ def test_dangerous_index_associations
14
+ Store.create!(name: "Test")
15
+ assert_raises(Searchkick::DangerousOperation) { Store.first.products.reindex }
16
+ end
17
+
18
+ def test_dangerous_reindex_accepted
19
+ store_names ["Product A", "Product B"]
20
+ Product.where(name: "Product A").reindex(accept_danger: true)
21
+ assert_search "product", ["Product A"]
22
+ end
23
+
24
+ def test_dangerous_reindex_inheritance
25
+ assert_raises(Searchkick::DangerousOperation) { Dog.where(id: [1, 2, 3]).reindex }
26
+ end
27
+ end
@@ -0,0 +1,90 @@
1
+ require_relative "test_helper"
2
+
3
+ class FacetsTest < Minitest::Test
4
+ def setup
5
+ skip unless elasticsearch_below20?
6
+ super
7
+ store [
8
+ {name: "Product Show", latitude: 37.7833, longitude: 12.4167, store_id: 1, in_stock: true, color: "blue", price: 21, created_at: 2.days.ago},
9
+ {name: "Product Hide", latitude: 29.4167, longitude: -98.5000, store_id: 2, in_stock: false, color: "green", price: 25, created_at: 2.days.from_now},
10
+ {name: "Product B", latitude: 43.9333, longitude: -122.4667, store_id: 2, in_stock: false, color: "red", price: 5},
11
+ {name: "Foo", latitude: 43.9333, longitude: 12.4667, store_id: 3, in_stock: false, color: "yellow", price: 15}
12
+ ]
13
+ end
14
+
15
+ def test_basic
16
+ assert_equal ({1 => 1, 2 => 2}), store_facet(facets: [:store_id])
17
+ end
18
+
19
+ def test_where
20
+ assert_equal ({1 => 1}), store_facet(facets: {store_id: {where: {in_stock: true}}})
21
+ end
22
+
23
+ def test_field
24
+ assert_equal ({1 => 1, 2 => 2}), store_facet(facets: {store_id: {}})
25
+ assert_equal ({1 => 1, 2 => 2}), store_facet(facets: {store_id: {field: "store_id"}})
26
+ assert_equal ({1 => 1, 2 => 2}), store_facet({facets: {store_id_new: {field: "store_id"}}}, "store_id_new")
27
+ end
28
+
29
+ def test_limit
30
+ facet = Product.search("Product", facets: {store_id: {limit: 1}}).facets["store_id"]
31
+ assert_equal 1, facet["terms"].size
32
+ assert_equal 3, facet["total"]
33
+ assert_equal 1, facet["other"]
34
+ end
35
+
36
+ def test_ranges
37
+ price_ranges = [{to: 10}, {from: 10, to: 20}, {from: 20}]
38
+ facet = Product.search("Product", facets: {price: {ranges: price_ranges}}).facets["price"]
39
+
40
+ assert_equal 3, facet["ranges"].size
41
+ assert_equal 10.0, facet["ranges"][0]["to"]
42
+ assert_equal 20.0, facet["ranges"][2]["from"]
43
+ assert_equal 1, facet["ranges"][0]["count"]
44
+ assert_equal 0, facet["ranges"][1]["count"]
45
+ assert_equal 2, facet["ranges"][2]["count"]
46
+ end
47
+
48
+ def test_ranges_dates
49
+ ranges = [{to: 1.day.ago}, {from: 1.day.ago, to: 1.day.from_now}, {from: 1.day.from_now}]
50
+ facet = Product.search("Product", facets: {created_at: {ranges: ranges}}).facets["created_at"]
51
+
52
+ assert_equal 1, facet["ranges"][0]["count"]
53
+ assert_equal 1, facet["ranges"][1]["count"]
54
+ assert_equal 1, facet["ranges"][2]["count"]
55
+ end
56
+
57
+ def test_where_no_smart_facets
58
+ assert_equal ({2 => 2}), store_facet(where: {color: "red"}, facets: {store_id: {where: {in_stock: false}}})
59
+ end
60
+
61
+ def test_smart_facets
62
+ assert_equal ({1 => 1}), store_facet(where: {in_stock: true}, facets: [:store_id], smart_facets: true)
63
+ end
64
+
65
+ def test_smart_facets_where
66
+ assert_equal ({2 => 1}), store_facet(where: {color: "red"}, facets: {store_id: {where: {in_stock: false}}}, smart_facets: true)
67
+ end
68
+
69
+ def test_smart_facets_skip_facet
70
+ assert_equal ({1 => 1, 2 => 2}), store_facet(where: {store_id: 2}, facets: [:store_id], smart_facets: true)
71
+ end
72
+
73
+ def test_smart_facets_skip_facet_complex
74
+ assert_equal ({1 => 1, 2 => 1}), store_facet(where: {store_id: 2, price: {gt: 5}}, facets: [:store_id], smart_facets: true)
75
+ end
76
+
77
+ def test_stats_facets
78
+ skip if Gem::Version.new(Searchkick.server_version) >= Gem::Version.new("1.4.0")
79
+ options = {where: {store_id: 2}, facets: {store_id: {stats: true}}}
80
+ facets = Product.search("Product", options).facets["store_id"]["terms"]
81
+ expected_facets_keys = %w(term count total_count min max total mean)
82
+ assert_equal expected_facets_keys, facets.first.keys
83
+ end
84
+
85
+ protected
86
+
87
+ def store_facet(options, facet_key = "store_id")
88
+ Hash[Product.search("Product", options).facets[facet_key]["terms"].map { |v| [v["term"], v["count"]] }]
89
+ end
90
+ end
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "sqlite3"
7
+ gem "activerecord", "~> 3.1.0"
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "sqlite3"
7
+ gem "activerecord", "~> 3.2.0"
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "sqlite3"
7
+ gem "activerecord", "~> 4.0.0"
8
+ gem "activejob_backport"
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "sqlite3"
7
+ gem "activerecord", "~> 4.1.0"
8
+ gem "activejob_backport"
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "sqlite3"
7
+ gem "activerecord", "~> 5.0.0.rc1"
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "sqlite3"
7
+ gem "activerecord", "~> 4.2.0"
8
+ gem "apartment"
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "mongoid", "~> 2"
7
+ gem "bson_ext"
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "mongoid", "~> 3.1.0"
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "mongoid", "~> 4.0.0"
7
+ gem "activejob_backport"
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "mongoid", "~> 5.0.0"
7
+ gem "activejob_backport"
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in searchkick.gemspec
4
+ gemspec path: "../../"
5
+
6
+ gem "nobrainer", "0.27.0"
@@ -0,0 +1,63 @@
1
+ require_relative "test_helper"
2
+
3
+ class HighlightTest < Minitest::Test
4
+ def test_basic
5
+ store_names ["Two Door Cinema Club"]
6
+ assert_equal "Two Door <em>Cinema</em> Club", Product.search("cinema", fields: [:name], highlight: true).with_details.first[1][:highlight][:name]
7
+ end
8
+
9
+ def test_tag
10
+ store_names ["Two Door Cinema Club"]
11
+ assert_equal "Two Door <strong>Cinema</strong> Club", Product.search("cinema", fields: [:name], highlight: {tag: "<strong>"}).with_details.first[1][:highlight][:name]
12
+ end
13
+
14
+ def test_multiple_fields
15
+ store [{name: "Two Door Cinema Club", color: "Cinema Orange"}]
16
+ highlight = Product.search("cinema", fields: [:name, :color], highlight: true).with_details.first[1][:highlight]
17
+ assert_equal "Two Door <em>Cinema</em> Club", highlight[:name]
18
+ assert_equal "<em>Cinema</em> Orange", highlight[:color]
19
+ end
20
+
21
+ def test_fields
22
+ store [{name: "Two Door Cinema Club", color: "Cinema Orange"}]
23
+ highlight = Product.search("cinema", fields: [:name, :color], highlight: {fields: [:name]}).with_details.first[1][:highlight]
24
+ assert_equal "Two Door <em>Cinema</em> Club", highlight[:name]
25
+ assert_equal nil, highlight[:color]
26
+ end
27
+
28
+ def test_field_options
29
+ store_names ["Two Door Cinema Club are a Northern Irish indie rock band"]
30
+ fragment_size = ENV["MATCH"] == "word_start" ? 26 : 20
31
+ assert_equal "Two Door <em>Cinema</em> Club are", Product.search("cinema", fields: [:name], highlight: {fields: {name: {fragment_size: fragment_size}}}).with_details.first[1][:highlight][:name]
32
+ end
33
+
34
+ def test_multiple_words
35
+ store_names ["Hello World Hello"]
36
+ assert_equal "<em>Hello</em> World <em>Hello</em>", Product.search("hello", fields: [:name], highlight: true).with_details.first[1][:highlight][:name]
37
+ end
38
+
39
+ def test_encoder
40
+ store_names ["<b>Hello</b>"]
41
+ assert_equal "&lt;b&gt;<em>Hello</em>&lt;&#x2F;b&gt;", Product.search("hello", fields: [:name], highlight: {encoder: "html"}, misspellings: false).with_details.first[1][:highlight][:name]
42
+ end
43
+
44
+ def test_json
45
+ skip if ENV["MATCH"] == "word_start"
46
+ store_names ["Two Door Cinema Club"]
47
+ json = {
48
+ query: {
49
+ match: {
50
+ "name.analyzed" => "cinema"
51
+ }
52
+ },
53
+ highlight: {
54
+ pre_tags: ["<strong>"],
55
+ post_tags: ["</strong>"],
56
+ fields: {
57
+ "name.analyzed" => {}
58
+ }
59
+ }
60
+ }
61
+ assert_equal "Two Door <strong>Cinema</strong> Club", Product.search(json: json).with_details.first[1][:highlight][:"name.analyzed"]
62
+ end
63
+ end
@@ -0,0 +1,120 @@
1
+ require_relative "test_helper"
2
+
3
+ class IndexTest < Minitest::Test
4
+ def test_clean_indices
5
+ old_index = Searchkick::Index.new("products_test_20130801000000000")
6
+ different_index = Searchkick::Index.new("items_test_20130801000000000")
7
+
8
+ old_index.delete if old_index.exists?
9
+ different_index.delete if different_index.exists?
10
+
11
+ # create indexes
12
+ old_index.create
13
+ different_index.create
14
+
15
+ Product.clean_indices
16
+
17
+ assert Product.searchkick_index.exists?
18
+ assert different_index.exists?
19
+ assert !old_index.exists?
20
+ end
21
+
22
+ def test_clean_indices_old_format
23
+ old_index = Searchkick::Index.new("products_test_20130801000000")
24
+ old_index.create
25
+
26
+ Product.clean_indices
27
+
28
+ assert !old_index.exists?
29
+ end
30
+
31
+ def test_mapping
32
+ store_names ["Dollar Tree"], Store
33
+ assert_equal [], Store.search(query: {match: {name: "dollar"}}).map(&:name)
34
+ assert_equal ["Dollar Tree"], Store.search(query: {match: {name: "Dollar Tree"}}).map(&:name)
35
+ end
36
+
37
+ def test_json
38
+ store_names ["Dollar Tree"], Store
39
+ assert_equal [], Store.search(query: {match: {name: "dollar"}}).map(&:name)
40
+ assert_equal ["Dollar Tree"], Store.search(json: {query: {match: {name: "Dollar Tree"}}}, load: false).map(&:name)
41
+ end
42
+
43
+ def test_body
44
+ store_names ["Dollar Tree"], Store
45
+ assert_equal [], Store.search(query: {match: {name: "dollar"}}).map(&:name)
46
+ assert_equal ["Dollar Tree"], Store.search(body: {query: {match: {name: "Dollar Tree"}}}, load: false).map(&:name)
47
+ end
48
+
49
+ def test_block
50
+ store_names ["Dollar Tree"]
51
+ products =
52
+ Product.search "boom" do |body|
53
+ body[:query] = {match_all: {}}
54
+ end
55
+ assert_equal ["Dollar Tree"], products.map(&:name)
56
+ end
57
+
58
+ def test_tokens
59
+ assert_equal ["dollar", "dollartre", "tree"], Product.searchkick_index.tokens("Dollar Tree")
60
+ end
61
+
62
+ def test_tokens_analyzer
63
+ assert_equal ["dollar", "tree"], Product.searchkick_index.tokens("Dollar Tree", analyzer: "searchkick_search2")
64
+ end
65
+
66
+ def test_record_not_found
67
+ store_names ["Product A", "Product B"]
68
+ Product.where(name: "Product A").delete_all
69
+ assert_search "product", ["Product B"]
70
+ ensure
71
+ Product.reindex
72
+ end
73
+
74
+ def test_bad_mapping
75
+ Product.searchkick_index.delete
76
+ store_names ["Product A"]
77
+ assert_raises(Searchkick::InvalidQueryError) { Product.search "test" }
78
+ ensure
79
+ Product.reindex
80
+ end
81
+
82
+ def test_remove_blank_id
83
+ store_names ["Product A"]
84
+ Product.searchkick_index.remove(OpenStruct.new)
85
+ assert_search "product", ["Product A"]
86
+ ensure
87
+ Product.reindex
88
+ end
89
+
90
+ def test_missing_index
91
+ assert_raises(Searchkick::MissingIndexError) { Product.search "test", index_name: "not_found" }
92
+ end
93
+
94
+ def test_unsupported_version
95
+ raises_exception = ->(_) { raise Elasticsearch::Transport::Transport::Error.new("[500] No query registered for [multi_match]") }
96
+ Searchkick.client.stub :search, raises_exception do
97
+ assert_raises(Searchkick::UnsupportedVersionError) { Product.search("test") }
98
+ end
99
+ end
100
+
101
+ def test_invalid_query
102
+ assert_raises(Searchkick::InvalidQueryError) { Product.search(query: {boom: true}) }
103
+ end
104
+
105
+ def test_transaction
106
+ skip unless defined?(ActiveRecord)
107
+ Product.transaction do
108
+ store_names ["Product A"]
109
+ raise ActiveRecord::Rollback
110
+ end
111
+ assert_search "product", []
112
+ end
113
+
114
+ def test_analyzed_only
115
+ skip if nobrainer?
116
+ large_value = 10000.times.map { "hello" }.join(" ")
117
+ store [{name: "Product A", alt_description: large_value}]
118
+ assert_search "product", ["Product A"]
119
+ end
120
+ end
@@ -0,0 +1,78 @@
1
+ require_relative "test_helper"
2
+
3
+ class InheritanceTest < Minitest::Test
4
+ def test_child_reindex
5
+ store_names ["Max"], Cat
6
+ assert Dog.reindex
7
+ Animal.searchkick_index.refresh
8
+ assert_equal 1, Animal.search("*").size
9
+ end
10
+
11
+ def test_child_index_name
12
+ assert_equal "animals-#{Date.today.year}", Dog.searchkick_index.name
13
+ end
14
+
15
+ def test_child_search
16
+ store_names ["Bear"], Dog
17
+ store_names ["Bear"], Cat
18
+ assert_equal 1, Dog.search("bear").size
19
+ end
20
+
21
+ def test_parent_search
22
+ store_names ["Bear"], Dog
23
+ store_names ["Bear"], Cat
24
+ assert_equal 2, Animal.search("bear").size
25
+ end
26
+
27
+ def test_force_one_type
28
+ store_names ["Green Bear"], Dog
29
+ store_names ["Blue Bear"], Cat
30
+ assert_equal ["Blue Bear"], Animal.search("bear", type: [Cat]).map(&:name)
31
+ end
32
+
33
+ def test_force_multiple_types
34
+ store_names ["Green Bear"], Dog
35
+ store_names ["Blue Bear"], Cat
36
+ store_names ["Red Bear"], Animal
37
+ assert_equal ["Green Bear", "Blue Bear"], Animal.search("bear", type: [Dog, Cat]).map(&:name)
38
+ end
39
+
40
+ def test_child_autocomplete
41
+ store_names ["Max"], Cat
42
+ store_names ["Mark"], Dog
43
+ assert_equal ["Max"], Cat.search("ma", fields: [:name], autocomplete: true).map(&:name)
44
+ end
45
+
46
+ def test_parent_autocomplete
47
+ store_names ["Max"], Cat
48
+ store_names ["Bear"], Dog
49
+ assert_equal ["Bear"], Animal.search("bea", fields: [:name], autocomplete: true).map(&:name).sort
50
+ end
51
+
52
+ # def test_child_suggest
53
+ # store_names ["Shark"], Cat
54
+ # store_names ["Sharp"], Dog
55
+ # assert_equal ["shark"], Cat.search("shar", fields: [:name], suggest: true).suggestions
56
+ # end
57
+
58
+ def test_parent_suggest
59
+ store_names ["Shark"], Cat
60
+ store_names ["Tiger"], Dog
61
+ assert_equal ["tiger"], Animal.search("tige", fields: [:name], suggest: true).suggestions.sort
62
+ end
63
+
64
+ def test_reindex
65
+ store_names ["Bear A"], Cat
66
+ store_names ["Bear B"], Dog
67
+ Animal.reindex
68
+ assert_equal 1, Dog.search("bear").size
69
+ end
70
+
71
+ # TODO move somewhere better
72
+
73
+ def test_multiple_indices
74
+ store_names ["Product A"]
75
+ store_names ["Product B"], Animal
76
+ assert_search "product", ["Product A", "Product B"], index_name: [Product.searchkick_index.name, Animal.searchkick_index.name], conversions: false
77
+ end
78
+ end