searchkick 5.0.0 → 5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/README.md +18 -10
- data/lib/searchkick/index.rb +29 -15
- data/lib/searchkick/index_options.rb +1 -1
- data/lib/searchkick/model.rb +9 -7
- data/lib/searchkick/query.rb +2 -2
- data/lib/searchkick/record_data.rb +1 -0
- data/lib/searchkick/record_indexer.rb +2 -2
- data/lib/searchkick/reindex_queue.rb +1 -1
- data/lib/searchkick/results.rb +5 -5
- data/lib/searchkick/version.rb +1 -1
- data/lib/searchkick.rb +4 -4
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ab19b7696cc775bda54eef31aaf9fea04a13a3027335440023f58f0c3b761fa0
|
4
|
+
data.tar.gz: 461f230a62f440e84684e9eb42cc85d307b726830eba80999c5648aef13de92e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5382e2de584271fc9f80802f858329c613f3b9aff7877c9bb9653dab550deb6ed1ac6971cbb2bc306f4d6e67056f16ee98eea04d69f2fd9ff15fd899e37f8962
|
7
|
+
data.tar.gz: dd8121e4991c9aaad5cd331cdc3adef3c703ee47abf8238ea3cc6feb1b1e5dcd85cb59c9f7ce91c086644d5946c5ccba936f48d0bc27988a59cca81adf161bb3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
## 5.0.1 (2022-02-27)
|
2
|
+
|
3
|
+
- Prefer `mode: :async` over `async: true` for full reindex
|
4
|
+
- Fixed instance method overriding with concerns
|
5
|
+
|
1
6
|
## 5.0.0 (2022-02-21)
|
2
7
|
|
3
8
|
- Searches now use lazy loading (similar to Active Record)
|
@@ -15,7 +20,7 @@
|
|
15
20
|
- Raise error when `search` called on relations
|
16
21
|
- Raise `ArgumentError` (instead of warning) for invalid regular expression modifiers
|
17
22
|
- Raise `ArgumentError` instead of `RuntimeError` for unknown operators
|
18
|
-
- Removed mapping of `id` to `_id` with `order` option
|
23
|
+
- Removed mapping of `id` to `_id` with `order` option (not supported in Elasticsearch 8)
|
19
24
|
- Removed `wordnet` option (no longer worked)
|
20
25
|
- Removed dependency on `elasticsearch` gem (can use `elasticsearch` or `opensearch-ruby`)
|
21
26
|
- Dropped support for Elasticsearch 6
|
data/README.md
CHANGED
@@ -596,7 +596,7 @@ You can also do bulk updates.
|
|
596
596
|
|
597
597
|
```ruby
|
598
598
|
Searchkick.callbacks(:bulk) do
|
599
|
-
|
599
|
+
Product.find_each(&:update_fields)
|
600
600
|
end
|
601
601
|
```
|
602
602
|
|
@@ -604,7 +604,7 @@ Or temporarily skip updates.
|
|
604
604
|
|
605
605
|
```ruby
|
606
606
|
Searchkick.callbacks(false) do
|
607
|
-
|
607
|
+
Product.find_each(&:update_fields)
|
608
608
|
end
|
609
609
|
```
|
610
610
|
|
@@ -1100,7 +1100,7 @@ Product.search_index.tokens("dieg", analyzer: "searchkick_word_search")
|
|
1100
1100
|
# ["dieg"] - match!!
|
1101
1101
|
```
|
1102
1102
|
|
1103
|
-
See the [complete list of analyzers](
|
1103
|
+
See the [complete list of analyzers](lib/searchkick/index_options.rb#L36).
|
1104
1104
|
|
1105
1105
|
## Testing
|
1106
1106
|
|
@@ -1376,13 +1376,13 @@ Bonsai, Elastic Cloud, and Amazon OpenSearch Service all support encryption at r
|
|
1376
1376
|
|
1377
1377
|
### Automatic Failover
|
1378
1378
|
|
1379
|
-
Create an initializer
|
1379
|
+
Create an initializer with multiple hosts:
|
1380
1380
|
|
1381
1381
|
```ruby
|
1382
1382
|
ENV["ELASTICSEARCH_URL"] = "https://user:password@host1,https://user:password@host2"
|
1383
1383
|
```
|
1384
1384
|
|
1385
|
-
See [
|
1385
|
+
See [elastic-transport](https://github.com/elastic/elastic-transport-ruby) or [opensearch-transport](https://github.com/opensearch-project/opensearch-ruby/tree/main/opensearch-transport) for a complete list of options.
|
1386
1386
|
|
1387
1387
|
### Lograge
|
1388
1388
|
|
@@ -1453,7 +1453,7 @@ end
|
|
1453
1453
|
For large data sets, you can use background jobs to parallelize reindexing.
|
1454
1454
|
|
1455
1455
|
```ruby
|
1456
|
-
Product.reindex(
|
1456
|
+
Product.reindex(mode: :async)
|
1457
1457
|
# {index_name: "products_production_20170111210018065"}
|
1458
1458
|
```
|
1459
1459
|
|
@@ -1478,7 +1478,7 @@ Searchkick.reindex_status(index_name)
|
|
1478
1478
|
You can also have Searchkick wait for reindexing to complete
|
1479
1479
|
|
1480
1480
|
```ruby
|
1481
|
-
Product.reindex(
|
1481
|
+
Product.reindex(mode: :async, wait: true)
|
1482
1482
|
```
|
1483
1483
|
|
1484
1484
|
You can use [ActiveJob::TrafficControl](https://github.com/nickelser/activejob-traffic_control) to control concurrency. Install the gem:
|
@@ -1504,7 +1504,7 @@ This will allow only 3 jobs to run at once.
|
|
1504
1504
|
You can specify a longer refresh interval while reindexing to increase performance.
|
1505
1505
|
|
1506
1506
|
```ruby
|
1507
|
-
Product.reindex(
|
1507
|
+
Product.reindex(mode: :async, refresh_interval: "30s")
|
1508
1508
|
```
|
1509
1509
|
|
1510
1510
|
**Note:** This only makes a noticable difference with parallel reindexing.
|
@@ -1711,7 +1711,7 @@ products =
|
|
1711
1711
|
|
1712
1712
|
### Client
|
1713
1713
|
|
1714
|
-
|
1714
|
+
To access the `Elasticsearch::Client` or `OpenSearch::Client` directly, use:
|
1715
1715
|
|
1716
1716
|
```ruby
|
1717
1717
|
Searchkick.client
|
@@ -2087,9 +2087,17 @@ Product.search("milk")
|
|
2087
2087
|
Product.search("milk").to_a
|
2088
2088
|
```
|
2089
2089
|
|
2090
|
+
You can reindex relations in the background:
|
2091
|
+
|
2092
|
+
```ruby
|
2093
|
+
store.products.reindex(mode: :async)
|
2094
|
+
# or
|
2095
|
+
store.products.reindex(mode: :queue)
|
2096
|
+
```
|
2097
|
+
|
2090
2098
|
And there’s a [new option](#default-scopes) for models with default scopes.
|
2091
2099
|
|
2092
|
-
Check out the [changelog](https://github.com/ankane/searchkick/blob/master/CHANGELOG.md) for the full list of changes.
|
2100
|
+
Check out the [changelog](https://github.com/ankane/searchkick/blob/master/CHANGELOG.md#500-2022-02-21) for the full list of changes.
|
2093
2101
|
|
2094
2102
|
## History
|
2095
2103
|
|
data/lib/searchkick/index.rb
CHANGED
@@ -71,12 +71,12 @@ module Searchkick
|
|
71
71
|
}
|
72
72
|
)
|
73
73
|
|
74
|
-
|
74
|
+
Results.new(nil, response).total_count
|
75
75
|
end
|
76
76
|
|
77
77
|
def promote(new_name, update_refresh_interval: false)
|
78
78
|
if update_refresh_interval
|
79
|
-
new_index =
|
79
|
+
new_index = Index.new(new_name, @options)
|
80
80
|
settings = options[:settings] || {}
|
81
81
|
refresh_interval = (settings[:index] && settings[:index][:refresh_interval]) || "1s"
|
82
82
|
new_index.update_settings(index: {refresh_interval: refresh_interval})
|
@@ -123,7 +123,7 @@ module Searchkick
|
|
123
123
|
def clean_indices
|
124
124
|
indices = all_indices(unaliased: true)
|
125
125
|
indices.each do |index|
|
126
|
-
|
126
|
+
Index.new(index).delete
|
127
127
|
end
|
128
128
|
indices
|
129
129
|
end
|
@@ -204,7 +204,7 @@ module Searchkick
|
|
204
204
|
# queue
|
205
205
|
|
206
206
|
def reindex_queue
|
207
|
-
|
207
|
+
ReindexQueue.new(name)
|
208
208
|
end
|
209
209
|
|
210
210
|
# reindex
|
@@ -237,13 +237,26 @@ module Searchkick
|
|
237
237
|
self.refresh if refresh
|
238
238
|
true
|
239
239
|
else
|
240
|
+
async = options.delete(:async)
|
241
|
+
if async
|
242
|
+
if async.is_a?(Hash) && async[:wait]
|
243
|
+
# TODO warn in 5.1
|
244
|
+
# Searchkick.warn "async option is deprecated - use mode: :async, wait: true instead"
|
245
|
+
options[:wait] = true unless options.key?(:wait)
|
246
|
+
else
|
247
|
+
# TODO warn in 5.1
|
248
|
+
# Searchkick.warn "async option is deprecated - use mode: :async instead"
|
249
|
+
end
|
250
|
+
options[:mode] ||= :async
|
251
|
+
end
|
252
|
+
|
240
253
|
full_reindex(relation, **options)
|
241
254
|
end
|
242
255
|
end
|
243
256
|
|
244
257
|
def create_index(index_options: nil)
|
245
258
|
index_options ||= self.index_options
|
246
|
-
index =
|
259
|
+
index = Index.new("#{name}_#{Time.now.strftime('%Y%m%d%H%M%S%L')}", @options)
|
247
260
|
index.create(index_options)
|
248
261
|
index
|
249
262
|
end
|
@@ -326,7 +339,7 @@ module Searchkick
|
|
326
339
|
end
|
327
340
|
|
328
341
|
def reindex_records(object, mode: nil, refresh: false, **options)
|
329
|
-
mode ||= Searchkick.callbacks_value || @options[:callbacks] ||
|
342
|
+
mode ||= Searchkick.callbacks_value || @options[:callbacks] || :inline
|
330
343
|
mode = :inline if mode == :bulk
|
331
344
|
|
332
345
|
result = RecordIndexer.new(self).reindex(object, mode: mode, full: false, **options)
|
@@ -336,12 +349,13 @@ module Searchkick
|
|
336
349
|
|
337
350
|
# https://gist.github.com/jarosan/3124884
|
338
351
|
# http://www.elasticsearch.org/blog/changing-mapping-with-zero-downtime/
|
339
|
-
|
340
|
-
|
352
|
+
def full_reindex(relation, import: true, resume: false, retain: false, mode: nil, refresh_interval: nil, scope: nil, wait: nil)
|
353
|
+
raise ArgumentError, "wait only available in :async mode" if !wait.nil? && mode != :async
|
354
|
+
|
341
355
|
if resume
|
342
356
|
index_name = all_indices.sort.last
|
343
|
-
raise
|
344
|
-
index =
|
357
|
+
raise Error, "No index to resume" unless index_name
|
358
|
+
index = Index.new(index_name, @options)
|
345
359
|
else
|
346
360
|
clean_indices unless retain
|
347
361
|
|
@@ -351,7 +365,7 @@ module Searchkick
|
|
351
365
|
end
|
352
366
|
|
353
367
|
import_options = {
|
354
|
-
mode: (
|
368
|
+
mode: (mode || :inline),
|
355
369
|
full: true,
|
356
370
|
resume: resume,
|
357
371
|
scope: scope
|
@@ -365,7 +379,7 @@ module Searchkick
|
|
365
379
|
import_before_promotion(index, relation, **import_options) if import
|
366
380
|
|
367
381
|
# get existing indices to remove
|
368
|
-
unless async
|
382
|
+
unless mode == :async
|
369
383
|
check_uuid(uuid, index.uuid)
|
370
384
|
promote(index.name, update_refresh_interval: !refresh_interval.nil?)
|
371
385
|
clean_indices unless retain
|
@@ -378,8 +392,8 @@ module Searchkick
|
|
378
392
|
index.import_scope(relation, **import_options) if import
|
379
393
|
end
|
380
394
|
|
381
|
-
if async
|
382
|
-
if
|
395
|
+
if mode == :async
|
396
|
+
if wait
|
383
397
|
puts "Created index: #{index.name}"
|
384
398
|
puts "Jobs queued. Waiting..."
|
385
399
|
loop do
|
@@ -417,7 +431,7 @@ module Searchkick
|
|
417
431
|
# https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#index-creation
|
418
432
|
def check_uuid(old_uuid, new_uuid)
|
419
433
|
if old_uuid != new_uuid
|
420
|
-
raise
|
434
|
+
raise Error, "Safety check failed - only run one Model.reindex per model at a time"
|
421
435
|
end
|
422
436
|
end
|
423
437
|
|
@@ -513,7 +513,7 @@ module Searchkick
|
|
513
513
|
else
|
514
514
|
[:searchkick_search2, :searchkick_word_search].each do |analyzer|
|
515
515
|
unless settings[:analysis][:analyzer][analyzer].key?(:filter)
|
516
|
-
raise
|
516
|
+
raise Error, "Search synonyms are not supported yet for language"
|
517
517
|
end
|
518
518
|
|
519
519
|
settings[:analysis][:analyzer][analyzer][:filter].insert(2, "searchkick_synonym_graph")
|
data/lib/searchkick/model.rb
CHANGED
@@ -22,16 +22,18 @@ module Searchkick
|
|
22
22
|
raise ArgumentError, "Invalid value for callbacks"
|
23
23
|
end
|
24
24
|
|
25
|
+
base = self
|
26
|
+
|
25
27
|
mod = Module.new
|
26
28
|
include(mod)
|
27
29
|
mod.module_eval do
|
28
30
|
def reindex(method_name = nil, mode: nil, refresh: false)
|
29
31
|
self.class.searchkick_index.reindex([self], method_name: method_name, mode: mode, refresh: refresh, single: true)
|
30
|
-
end
|
32
|
+
end unless base.method_defined?(:reindex)
|
31
33
|
|
32
34
|
def similar(**options)
|
33
35
|
self.class.searchkick_index.similar_record(self, **options)
|
34
|
-
end
|
36
|
+
end unless base.method_defined?(:similar)
|
35
37
|
|
36
38
|
def search_data
|
37
39
|
data = respond_to?(:to_hash) ? to_hash : serializable_hash
|
@@ -39,11 +41,11 @@ module Searchkick
|
|
39
41
|
data.delete("_id")
|
40
42
|
data.delete("_type")
|
41
43
|
data
|
42
|
-
end
|
44
|
+
end unless base.method_defined?(:search_data)
|
43
45
|
|
44
46
|
def should_index?
|
45
47
|
true
|
46
|
-
end
|
48
|
+
end unless base.method_defined?(:should_index?)
|
47
49
|
end
|
48
50
|
|
49
51
|
class_eval do
|
@@ -64,10 +66,10 @@ module Searchkick
|
|
64
66
|
alias_method Searchkick.search_method_name, :searchkick_search if Searchkick.search_method_name
|
65
67
|
|
66
68
|
def searchkick_index(name: nil)
|
67
|
-
|
68
|
-
|
69
|
+
index_name = name || searchkick_index_name
|
70
|
+
index_name = index_name.call if index_name.respond_to?(:call)
|
69
71
|
index_cache = class_variable_get(:@@searchkick_index_cache)
|
70
|
-
index_cache.fetch(
|
72
|
+
index_cache.fetch(index_name) { Searchkick::Index.new(index_name, searchkick_options) }
|
71
73
|
end
|
72
74
|
alias_method :search_index, :searchkick_index unless method_defined?(:search_index)
|
73
75
|
|
data/lib/searchkick/query.rb
CHANGED
@@ -187,11 +187,11 @@ module Searchkick
|
|
187
187
|
end
|
188
188
|
|
189
189
|
# set execute for multi search
|
190
|
-
@execute =
|
190
|
+
@execute = Results.new(searchkick_klass, response, opts)
|
191
191
|
end
|
192
192
|
|
193
193
|
def retry_misspellings?(response)
|
194
|
-
@misspellings_below &&
|
194
|
+
@misspellings_below && Results.new(searchkick_klass, response).total_count < @misspellings_below
|
195
195
|
end
|
196
196
|
|
197
197
|
private
|
@@ -14,7 +14,7 @@ module Searchkick
|
|
14
14
|
case mode
|
15
15
|
when :async
|
16
16
|
unless defined?(ActiveJob)
|
17
|
-
raise
|
17
|
+
raise Error, "Active Job not found"
|
18
18
|
end
|
19
19
|
|
20
20
|
# we could likely combine ReindexV2Job, BulkReindexJob, and ProcessBatchJob
|
@@ -45,7 +45,7 @@ module Searchkick
|
|
45
45
|
end
|
46
46
|
when :queue
|
47
47
|
if method_name
|
48
|
-
raise
|
48
|
+
raise Error, "Partial reindex not supported with queue option"
|
49
49
|
end
|
50
50
|
|
51
51
|
index.reindex_queue.push_records(records)
|
data/lib/searchkick/results.rb
CHANGED
@@ -141,7 +141,7 @@ module Searchkick
|
|
141
141
|
|
142
142
|
def hits
|
143
143
|
if error
|
144
|
-
raise
|
144
|
+
raise Error, "Query error - use the error method to view it"
|
145
145
|
else
|
146
146
|
@response["hits"]["hits"]
|
147
147
|
end
|
@@ -178,7 +178,7 @@ module Searchkick
|
|
178
178
|
end
|
179
179
|
|
180
180
|
def scroll
|
181
|
-
raise
|
181
|
+
raise Error, "Pass `scroll` option to the search method for scrolling" unless scroll_id
|
182
182
|
|
183
183
|
if block_given?
|
184
184
|
records = self
|
@@ -191,10 +191,10 @@ module Searchkick
|
|
191
191
|
else
|
192
192
|
begin
|
193
193
|
# TODO Active Support notifications for this scroll call
|
194
|
-
|
194
|
+
Results.new(@klass, Searchkick.client.scroll(scroll: options[:scroll], body: {scroll_id: scroll_id}), @options)
|
195
195
|
rescue => e
|
196
196
|
if Searchkick.not_found_error?(e) && e.message =~ /search_context_missing_exception/i
|
197
|
-
raise
|
197
|
+
raise Error, "Scroll id has expired"
|
198
198
|
else
|
199
199
|
raise e
|
200
200
|
end
|
@@ -232,7 +232,7 @@ module Searchkick
|
|
232
232
|
index_alias = index.split("_")[0..-2].join("_")
|
233
233
|
Array((options[:index_mapping] || {})[index_alias])
|
234
234
|
end
|
235
|
-
raise
|
235
|
+
raise Error, "Unknown model for index: #{index}. Pass the `models` option to the search method." unless models.any?
|
236
236
|
index_models[index] = models
|
237
237
|
end
|
238
238
|
|
data/lib/searchkick/version.rb
CHANGED
data/lib/searchkick.rb
CHANGED
@@ -171,7 +171,7 @@ module Searchkick
|
|
171
171
|
end
|
172
172
|
|
173
173
|
options = options.merge(block: block) if block
|
174
|
-
|
174
|
+
Relation.new(klass, term, **options)
|
175
175
|
end
|
176
176
|
|
177
177
|
def self.multi_search(queries)
|
@@ -183,7 +183,7 @@ module Searchkick
|
|
183
183
|
body: queries.flat_map { |q| [q.params.except(:body).to_json, q.body.to_json] }.map { |v| "#{v}\n" }.join,
|
184
184
|
}
|
185
185
|
ActiveSupport::Notifications.instrument("multi_search.searchkick", event) do
|
186
|
-
|
186
|
+
MultiSearch.new(queries).perform
|
187
187
|
end
|
188
188
|
end
|
189
189
|
|
@@ -241,9 +241,9 @@ module Searchkick
|
|
241
241
|
end
|
242
242
|
|
243
243
|
def self.reindex_status(index_name)
|
244
|
-
raise
|
244
|
+
raise Error, "Redis not configured" unless redis
|
245
245
|
|
246
|
-
batches_left =
|
246
|
+
batches_left = Index.new(index_name).batches_left
|
247
247
|
{
|
248
248
|
completed: batches_left == 0,
|
249
249
|
batches_left: batches_left
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: searchkick
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.
|
4
|
+
version: 5.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-02-
|
11
|
+
date: 2022-02-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|