searchkick 2.3.2 → 5.2.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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +377 -84
- data/LICENSE.txt +1 -1
- data/README.md +859 -602
- data/lib/searchkick/bulk_reindex_job.rb +13 -9
- data/lib/searchkick/controller_runtime.rb +40 -0
- data/lib/searchkick/hash_wrapper.rb +12 -0
- data/lib/searchkick/index.rb +281 -356
- data/lib/searchkick/index_cache.rb +30 -0
- data/lib/searchkick/index_options.rb +487 -281
- data/lib/searchkick/indexer.rb +15 -8
- data/lib/searchkick/log_subscriber.rb +57 -0
- data/lib/searchkick/middleware.rb +9 -2
- data/lib/searchkick/model.rb +72 -118
- data/lib/searchkick/multi_search.rb +9 -10
- data/lib/searchkick/process_batch_job.rb +12 -15
- data/lib/searchkick/process_queue_job.rb +22 -13
- data/lib/searchkick/query.rb +458 -217
- data/lib/searchkick/railtie.rb +7 -0
- data/lib/searchkick/record_data.rb +128 -0
- data/lib/searchkick/record_indexer.rb +164 -0
- data/lib/searchkick/reindex_queue.rb +51 -9
- data/lib/searchkick/reindex_v2_job.rb +10 -32
- data/lib/searchkick/relation.rb +247 -0
- data/lib/searchkick/relation_indexer.rb +155 -0
- data/lib/searchkick/results.rb +201 -82
- data/lib/searchkick/version.rb +1 -1
- data/lib/searchkick/where.rb +11 -0
- data/lib/searchkick.rb +269 -97
- data/lib/tasks/searchkick.rake +37 -0
- metadata +24 -178
- data/.gitignore +0 -22
- data/.travis.yml +0 -39
- data/Gemfile +0 -16
- data/Rakefile +0 -20
- data/benchmark/Gemfile +0 -23
- data/benchmark/benchmark.rb +0 -97
- data/lib/searchkick/logging.rb +0 -242
- data/lib/searchkick/tasks.rb +0 -33
- data/searchkick.gemspec +0 -28
- data/test/aggs_test.rb +0 -197
- data/test/autocomplete_test.rb +0 -75
- data/test/boost_test.rb +0 -202
- data/test/callbacks_test.rb +0 -59
- data/test/ci/before_install.sh +0 -17
- data/test/errors_test.rb +0 -19
- data/test/gemfiles/activerecord31.gemfile +0 -7
- data/test/gemfiles/activerecord32.gemfile +0 -7
- data/test/gemfiles/activerecord40.gemfile +0 -8
- data/test/gemfiles/activerecord41.gemfile +0 -8
- data/test/gemfiles/activerecord42.gemfile +0 -7
- data/test/gemfiles/activerecord50.gemfile +0 -7
- data/test/gemfiles/apartment.gemfile +0 -8
- data/test/gemfiles/cequel.gemfile +0 -8
- data/test/gemfiles/mongoid2.gemfile +0 -7
- data/test/gemfiles/mongoid3.gemfile +0 -6
- data/test/gemfiles/mongoid4.gemfile +0 -7
- data/test/gemfiles/mongoid5.gemfile +0 -7
- data/test/gemfiles/mongoid6.gemfile +0 -12
- data/test/gemfiles/nobrainer.gemfile +0 -8
- data/test/gemfiles/parallel_tests.gemfile +0 -8
- data/test/geo_shape_test.rb +0 -175
- data/test/highlight_test.rb +0 -78
- data/test/index_test.rb +0 -166
- data/test/inheritance_test.rb +0 -83
- data/test/marshal_test.rb +0 -8
- data/test/match_test.rb +0 -276
- data/test/misspellings_test.rb +0 -56
- data/test/model_test.rb +0 -42
- data/test/multi_search_test.rb +0 -36
- data/test/multi_tenancy_test.rb +0 -22
- data/test/order_test.rb +0 -46
- data/test/pagination_test.rb +0 -70
- data/test/partial_reindex_test.rb +0 -58
- data/test/query_test.rb +0 -35
- data/test/records_test.rb +0 -10
- data/test/reindex_test.rb +0 -64
- data/test/reindex_v2_job_test.rb +0 -32
- data/test/routing_test.rb +0 -23
- data/test/should_index_test.rb +0 -32
- data/test/similar_test.rb +0 -28
- data/test/sql_test.rb +0 -214
- data/test/suggest_test.rb +0 -95
- data/test/support/kaminari.yml +0 -21
- data/test/synonyms_test.rb +0 -67
- data/test/test_helper.rb +0 -567
- data/test/where_test.rb +0 -223
data/test/sql_test.rb
DELETED
@@ -1,214 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class SqlTest < Minitest::Test
|
4
|
-
def test_operator
|
5
|
-
store_names ["Honey"]
|
6
|
-
assert_search "fresh honey", []
|
7
|
-
assert_search "fresh honey", ["Honey"], operator: "or"
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_operator_scoring
|
11
|
-
store_names ["Big Red Circle", "Big Green Circle", "Small Orange Circle"]
|
12
|
-
assert_order "big red circle", ["Big Red Circle", "Big Green Circle", "Small Orange Circle"], operator: "or"
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_fields_operator
|
16
|
-
store [
|
17
|
-
{name: "red", color: "red"},
|
18
|
-
{name: "blue", color: "blue"},
|
19
|
-
{name: "cyan", color: "blue green"},
|
20
|
-
{name: "magenta", color: "red blue"},
|
21
|
-
{name: "green", color: "green"}
|
22
|
-
]
|
23
|
-
assert_search "red blue", ["red", "blue", "cyan", "magenta"], operator: "or", fields: ["color"]
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_fields
|
27
|
-
store [
|
28
|
-
{name: "red", color: "light blue"},
|
29
|
-
{name: "blue", color: "red fish"}
|
30
|
-
]
|
31
|
-
assert_search "blue", ["red"], fields: ["color"]
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_non_existent_field
|
35
|
-
store_names ["Milk"]
|
36
|
-
assert_search "milk", [], fields: ["not_here"]
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_fields_both_match
|
40
|
-
store [
|
41
|
-
{name: "Blue A", color: "red"},
|
42
|
-
{name: "Blue B", color: "light blue"}
|
43
|
-
]
|
44
|
-
assert_first "blue", "Blue B", fields: [:name, :color]
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_big_decimal
|
48
|
-
store [
|
49
|
-
{name: "Product", latitude: 80.0}
|
50
|
-
]
|
51
|
-
assert_search "product", ["Product"], where: {latitude: {gt: 79}}
|
52
|
-
end
|
53
|
-
|
54
|
-
# body_options
|
55
|
-
|
56
|
-
def test_body_options_should_merge_into_body
|
57
|
-
query = Product.search("*", body_options: {min_score: 1.0}, execute: false)
|
58
|
-
assert_equal 1.0, query.body[:min_score]
|
59
|
-
end
|
60
|
-
|
61
|
-
# load
|
62
|
-
|
63
|
-
def test_load_default
|
64
|
-
store_names ["Product A"]
|
65
|
-
assert_kind_of Product, Product.search("product").first
|
66
|
-
end
|
67
|
-
|
68
|
-
def test_load_false
|
69
|
-
store_names ["Product A"]
|
70
|
-
assert_kind_of Hash, Product.search("product", load: false).first
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_load_false_methods
|
74
|
-
store_names ["Product A"]
|
75
|
-
assert_equal "Product A", Product.search("product", load: false).first.name
|
76
|
-
end
|
77
|
-
|
78
|
-
def test_load_false_with_includes
|
79
|
-
store_names ["Product A"]
|
80
|
-
assert_kind_of Hash, Product.search("product", load: false, includes: [:store]).first
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_load_false_nested_object
|
84
|
-
aisle = {"id" => 1, "name" => "Frozen"}
|
85
|
-
store [{name: "Product A", aisle: aisle}]
|
86
|
-
assert_equal aisle, Product.search("product", load: false).first.aisle.to_hash
|
87
|
-
end
|
88
|
-
|
89
|
-
# select
|
90
|
-
|
91
|
-
def test_select
|
92
|
-
store [{name: "Product A", store_id: 1}]
|
93
|
-
result = Product.search("product", load: false, select: [:name, :store_id]).first
|
94
|
-
assert_equal %w(id name store_id), result.keys.reject { |k| k.start_with?("_") }.sort
|
95
|
-
assert_equal "Product A", result.name
|
96
|
-
assert_equal 1, result.store_id
|
97
|
-
end
|
98
|
-
|
99
|
-
def test_select_array
|
100
|
-
store [{name: "Product A", user_ids: [1, 2]}]
|
101
|
-
result = Product.search("product", load: false, select: [:user_ids]).first
|
102
|
-
assert_equal [1, 2], result.user_ids
|
103
|
-
end
|
104
|
-
|
105
|
-
def test_select_single_field
|
106
|
-
store [{name: "Product A", store_id: 1}]
|
107
|
-
result = Product.search("product", load: false, select: :name).first
|
108
|
-
assert_equal %w(id name), result.keys.reject { |k| k.start_with?("_") }.sort
|
109
|
-
assert_equal "Product A", result.name
|
110
|
-
assert_nil result.store_id
|
111
|
-
end
|
112
|
-
|
113
|
-
def test_select_all
|
114
|
-
store [{name: "Product A", user_ids: [1, 2]}]
|
115
|
-
hit = Product.search("product", select: true).hits.first
|
116
|
-
assert_equal hit["_source"]["name"], "Product A"
|
117
|
-
assert_equal hit["_source"]["user_ids"], [1, 2]
|
118
|
-
end
|
119
|
-
|
120
|
-
def test_select_none
|
121
|
-
store [{name: "Product A", user_ids: [1, 2]}]
|
122
|
-
hit = Product.search("product", select: []).hits.first
|
123
|
-
assert_nil hit["_source"]
|
124
|
-
hit = Product.search("product", select: false).hits.first
|
125
|
-
assert_nil hit["_source"]
|
126
|
-
end
|
127
|
-
|
128
|
-
def test_select_include
|
129
|
-
skip unless elasticsearch_below50?
|
130
|
-
store [{name: "Product A", user_ids: [1, 2]}]
|
131
|
-
result = Product.search("product", load: false, select: {include: [:name]}).first
|
132
|
-
assert_equal %w(id name), result.keys.reject { |k| k.start_with?("_") }.sort
|
133
|
-
assert_equal "Product A", result.name
|
134
|
-
assert_nil result.store_id
|
135
|
-
end
|
136
|
-
|
137
|
-
def test_select_exclude
|
138
|
-
skip unless elasticsearch_below50?
|
139
|
-
store [{name: "Product A", user_ids: [1, 2], store_id: 1}]
|
140
|
-
result = Product.search("product", load: false, select: {exclude: [:name]}).first
|
141
|
-
assert_nil result.name
|
142
|
-
assert_equal [1, 2], result.user_ids
|
143
|
-
assert_equal 1, result.store_id
|
144
|
-
end
|
145
|
-
|
146
|
-
def test_select_include_and_exclude
|
147
|
-
skip unless elasticsearch_below50?
|
148
|
-
# let's take this to the next level
|
149
|
-
store [{name: "Product A", user_ids: [1, 2], store_id: 1}]
|
150
|
-
result = Product.search("product", load: false, select: {include: [:store_id], exclude: [:name]}).first
|
151
|
-
assert_equal 1, result.store_id
|
152
|
-
assert_nil result.name
|
153
|
-
assert_nil result.user_ids
|
154
|
-
end
|
155
|
-
|
156
|
-
def test_select_includes
|
157
|
-
skip if elasticsearch_below50?
|
158
|
-
store [{name: "Product A", user_ids: [1, 2]}]
|
159
|
-
result = Product.search("product", load: false, select: {includes: [:name]}).first
|
160
|
-
assert_equal %w(id name), result.keys.reject { |k| k.start_with?("_") }.sort
|
161
|
-
assert_equal "Product A", result.name
|
162
|
-
assert_nil result.store_id
|
163
|
-
end
|
164
|
-
|
165
|
-
def test_select_excludes
|
166
|
-
skip if elasticsearch_below50?
|
167
|
-
store [{name: "Product A", user_ids: [1, 2], store_id: 1}]
|
168
|
-
result = Product.search("product", load: false, select: {excludes: [:name]}).first
|
169
|
-
assert_nil result.name
|
170
|
-
assert_equal [1, 2], result.user_ids
|
171
|
-
assert_equal 1, result.store_id
|
172
|
-
end
|
173
|
-
|
174
|
-
def test_select_include_and_excludes
|
175
|
-
skip if elasticsearch_below50?
|
176
|
-
# let's take this to the next level
|
177
|
-
store [{name: "Product A", user_ids: [1, 2], store_id: 1}]
|
178
|
-
result = Product.search("product", load: false, select: {includes: [:store_id], excludes: [:name]}).first
|
179
|
-
assert_equal 1, result.store_id
|
180
|
-
assert_nil result.name
|
181
|
-
assert_nil result.user_ids
|
182
|
-
end
|
183
|
-
|
184
|
-
# nested
|
185
|
-
|
186
|
-
def test_nested_search
|
187
|
-
store [{name: "Product A", aisle: {"id" => 1, "name" => "Frozen"}}], Speaker
|
188
|
-
assert_search "frozen", ["Product A"], {fields: ["aisle.name"]}, Speaker
|
189
|
-
end
|
190
|
-
|
191
|
-
# other tests
|
192
|
-
|
193
|
-
def test_includes
|
194
|
-
skip unless defined?(ActiveRecord)
|
195
|
-
store_names ["Product A"]
|
196
|
-
assert Product.search("product", includes: [:store]).first.association(:store).loaded?
|
197
|
-
end
|
198
|
-
|
199
|
-
def test_model_includes
|
200
|
-
skip unless defined?(ActiveRecord)
|
201
|
-
|
202
|
-
store_names ["Product A"]
|
203
|
-
store_names ["Store A"], Store
|
204
|
-
|
205
|
-
associations = {Product => [:store], Store => [:products]}
|
206
|
-
result = Searchkick.search("*", index_name: [Product, Store], model_includes: associations)
|
207
|
-
|
208
|
-
assert_equal 2, result.length
|
209
|
-
|
210
|
-
result.group_by(&:class).each_pair do |klass, records|
|
211
|
-
assert records.first.association(associations[klass].first).loaded?
|
212
|
-
end
|
213
|
-
end
|
214
|
-
end
|
data/test/suggest_test.rb
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class SuggestTest < Minitest::Test
|
4
|
-
def test_basic
|
5
|
-
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]
|
7
|
-
end
|
8
|
-
|
9
|
-
def test_perfect
|
10
|
-
store_names ["Tiger Shark", "Great White Shark"]
|
11
|
-
assert_suggest "Tiger Shark", nil, fields: [:name] # no correction
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_phrase
|
15
|
-
store_names ["Big Tiger Shark", "Tiger Sharp Teeth", "Tiger Sharp Mind"]
|
16
|
-
assert_suggest "How to catch a big tiger shar", "how to catch a big tiger shark", fields: [:name]
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_without_option
|
20
|
-
store_names ["hi"] # needed to prevent ElasticsearchException - seed 668
|
21
|
-
assert_raises(RuntimeError) { Product.search("hi").suggestions }
|
22
|
-
end
|
23
|
-
|
24
|
-
def test_multiple_fields
|
25
|
-
store [
|
26
|
-
{name: "Shark", color: "Sharp"},
|
27
|
-
{name: "Shark", color: "Sharp"}
|
28
|
-
]
|
29
|
-
assert_suggest_all "shar", ["shark", "sharp"]
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_multiple_fields_highest_score_first
|
33
|
-
store [
|
34
|
-
{name: "Tiger Shark", color: "Sharp"}
|
35
|
-
]
|
36
|
-
assert_suggest "tiger shar", "tiger shark"
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_multiple_fields_same_value
|
40
|
-
store [
|
41
|
-
{name: "Shark", color: "Shark"}
|
42
|
-
]
|
43
|
-
assert_suggest_all "shar", ["shark"]
|
44
|
-
end
|
45
|
-
|
46
|
-
def test_fields_option
|
47
|
-
store [
|
48
|
-
{name: "Shark", color: "Sharp"}
|
49
|
-
]
|
50
|
-
assert_suggest_all "shar", ["shark"], fields: [:name]
|
51
|
-
end
|
52
|
-
|
53
|
-
def test_fields_option_multiple
|
54
|
-
store [
|
55
|
-
{name: "Shark"}
|
56
|
-
]
|
57
|
-
assert_suggest "shar", "shark", fields: [:name, :unknown]
|
58
|
-
end
|
59
|
-
|
60
|
-
def test_fields_partial_match
|
61
|
-
store_names ["Great White Shark", "Hammerhead Shark", "Tiger Shark"]
|
62
|
-
assert_suggest "How Big is a Tigre Shar", "how big is a tiger shark", fields: [{name: :word_start}]
|
63
|
-
end
|
64
|
-
|
65
|
-
def test_fields_partial_match_boost
|
66
|
-
store_names ["Great White Shark", "Hammerhead Shark", "Tiger Shark"]
|
67
|
-
assert_suggest "How Big is a Tigre Shar", "how big is a tiger shark", fields: [{"name^2" => :word_start}]
|
68
|
-
end
|
69
|
-
|
70
|
-
def test_multiple_models
|
71
|
-
store_names ["Great White Shark", "Hammerhead Shark", "Tiger Shark"]
|
72
|
-
assert_equal "how big is a tiger shark", Searchkick.search("How Big is a Tigre Shar", suggest: [:name], fields: [:name]).suggestions.first
|
73
|
-
end
|
74
|
-
|
75
|
-
def test_multiple_models_no_fields
|
76
|
-
store_names ["Great White Shark", "Hammerhead Shark", "Tiger Shark"]
|
77
|
-
assert_raises(ArgumentError) { Searchkick.search("How Big is a Tigre Shar", suggest: true) }
|
78
|
-
end
|
79
|
-
|
80
|
-
protected
|
81
|
-
|
82
|
-
def assert_suggest(term, expected, options = {})
|
83
|
-
result = Product.search(term, options.merge(suggest: true)).suggestions.first
|
84
|
-
if expected.nil?
|
85
|
-
assert_nil result
|
86
|
-
else
|
87
|
-
assert_equal expected, result
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
# any order
|
92
|
-
def assert_suggest_all(term, expected, options = {})
|
93
|
-
assert_equal expected.sort, Product.search(term, options.merge(suggest: true)).suggestions.sort
|
94
|
-
end
|
95
|
-
end
|
data/test/support/kaminari.yml
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
en:
|
2
|
-
views:
|
3
|
-
pagination:
|
4
|
-
first: "« First"
|
5
|
-
last: "Last »"
|
6
|
-
previous: "‹ Prev"
|
7
|
-
next: "Next ›"
|
8
|
-
truncate: "…"
|
9
|
-
helpers:
|
10
|
-
page_entries_info:
|
11
|
-
entry:
|
12
|
-
zero: "entries"
|
13
|
-
one: "entry"
|
14
|
-
other: "entries"
|
15
|
-
one_page:
|
16
|
-
display_entries:
|
17
|
-
zero: "No %{entry_name} found"
|
18
|
-
one: "Displaying <b>1</b> %{entry_name}"
|
19
|
-
other: "Displaying <b>all %{count}</b> %{entry_name}"
|
20
|
-
more_pages:
|
21
|
-
display_entries: "Displaying %{entry_name} <b>%{first} - %{last}</b> of <b>%{total}</b> in total"
|
data/test/synonyms_test.rb
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
require_relative "test_helper"
|
2
|
-
|
3
|
-
class SynonymsTest < Minitest::Test
|
4
|
-
def test_bleach
|
5
|
-
store_names ["Clorox Bleach", "Kroger Bleach"]
|
6
|
-
assert_search "clorox", ["Clorox Bleach", "Kroger Bleach"]
|
7
|
-
end
|
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
|
15
|
-
store_names ["Hamburger Buns"]
|
16
|
-
assert_search "burger buns", ["Hamburger Buns"]
|
17
|
-
end
|
18
|
-
|
19
|
-
def test_bandaids
|
20
|
-
store_names ["Band-Aid", "Kroger 12-Pack Bandages"]
|
21
|
-
assert_search "bandaids", ["Band-Aid", "Kroger 12-Pack Bandages"]
|
22
|
-
end
|
23
|
-
|
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
|
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"]
|
37
|
-
end
|
38
|
-
|
39
|
-
def test_stemmed
|
40
|
-
store_names ["Green Onions", "Yellow Onions"]
|
41
|
-
assert_search "scallions", ["Green Onions"]
|
42
|
-
end
|
43
|
-
|
44
|
-
def test_word_start
|
45
|
-
store_names ["Clorox Bleach", "Kroger Bleach"]
|
46
|
-
assert_search "clorox", ["Clorox Bleach", "Kroger Bleach"], fields: [{name: :word_start}]
|
47
|
-
end
|
48
|
-
|
49
|
-
def test_wordnet
|
50
|
-
skip unless ENV["TEST_WORDNET"]
|
51
|
-
store_names ["Creature", "Beast", "Dragon"], Animal
|
52
|
-
assert_search "animal", ["Creature", "Beast"], {}, Animal
|
53
|
-
end
|
54
|
-
|
55
|
-
def test_directional
|
56
|
-
store_names ["Lightbulb", "Green Onions", "Led"]
|
57
|
-
assert_search "led", ["Lightbulb", "Led"]
|
58
|
-
assert_search "Lightbulb", ["Lightbulb"]
|
59
|
-
assert_search "Halogen Lamp", ["Lightbulb"]
|
60
|
-
assert_search "onions", ["Green Onions"]
|
61
|
-
end
|
62
|
-
|
63
|
-
def test_case
|
64
|
-
store_names ["Uppercase"]
|
65
|
-
assert_search "lowercase", ["Uppercase"]
|
66
|
-
end
|
67
|
-
end
|