searchkick 5.0.0 → 5.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bc223f746f73c44e5c6f56b5e351cb31ae5a655069d92f5bfd2a0b2e531afae8
4
- data.tar.gz: 1969964f34a5adaf3ed746230fbef57673454f7304d890466e2814d27eb2cb47
3
+ metadata.gz: ab19b7696cc775bda54eef31aaf9fea04a13a3027335440023f58f0c3b761fa0
4
+ data.tar.gz: 461f230a62f440e84684e9eb42cc85d307b726830eba80999c5648aef13de92e
5
5
  SHA512:
6
- metadata.gz: 17259c3e071d69c3852584aba480b523211b167f1249951f32d1bd2f761fc07322144283f0ccabac4878c0a2ff2f4c9dd8def2db2beac004c449839052e503ea
7
- data.tar.gz: 1109a53d99eb30f7e76cab8df00505c82af5e898c4e3f1821773932b8f6917e68f6bfedfa952b8e4acb25387607edf10856cc994021943671086af4d751cc728
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
- User.find_each(&:update_fields)
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
- User.find_each(&:update_fields)
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](https://github.com/ankane/searchkick/blob/31780ddac7a89eab1e0552a32b403f2040a37931/lib/searchkick/index_options.rb#L32).
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 `config/initializers/elasticsearch.rb` with multiple hosts:
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 [elasticsearch-transport](https://github.com/elastic/elasticsearch-ruby/blob/master/elasticsearch-transport) for a complete list of options.
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(async: true)
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(async: {wait: true})
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(async: true, refresh_interval: "30s")
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
- Searchkick is built on top of the [elasticsearch](https://github.com/elastic/elasticsearch-ruby) gem. To access the client directly, use:
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
 
@@ -71,12 +71,12 @@ module Searchkick
71
71
  }
72
72
  )
73
73
 
74
- Searchkick::Results.new(nil, response).total_count
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 = Searchkick::Index.new(new_name, @options)
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
- Searchkick::Index.new(index).delete
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
- Searchkick::ReindexQueue.new(name)
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 = Searchkick::Index.new("#{name}_#{Time.now.strftime('%Y%m%d%H%M%S%L')}", @options)
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] || true
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
- # TODO deprecate async in favor of mode: :async, wait: true/false
340
- def full_reindex(relation, import: true, resume: false, retain: false, async: false, refresh_interval: nil, scope: nil)
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 Searchkick::Error, "No index to resume" unless index_name
344
- index = Searchkick::Index.new(index_name, @options)
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: (async ? :async : :inline),
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 async.is_a?(Hash) && async[:wait]
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 Searchkick::Error, "Safety check failed - only run one Model.reindex per model at a time"
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 Searchkick::Error, "Search synonyms are not supported yet for language"
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")
@@ -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
- index = name || searchkick_index_name
68
- index = index.call if index.respond_to?(:call)
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(index) { Searchkick::Index.new(index, searchkick_options) }
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
 
@@ -187,11 +187,11 @@ module Searchkick
187
187
  end
188
188
 
189
189
  # set execute for multi search
190
- @execute = Searchkick::Results.new(searchkick_klass, response, opts)
190
+ @execute = Results.new(searchkick_klass, response, opts)
191
191
  end
192
192
 
193
193
  def retry_misspellings?(response)
194
- @misspellings_below && Searchkick::Results.new(searchkick_klass, response).total_count < @misspellings_below
194
+ @misspellings_below && Results.new(searchkick_klass, response).total_count < @misspellings_below
195
195
  end
196
196
 
197
197
  private
@@ -25,6 +25,7 @@ module Searchkick
25
25
  {delete: record_data}
26
26
  end
27
27
 
28
+ # custom id can be useful for load: false
28
29
  def search_id
29
30
  id = record.respond_to?(:search_document_id) ? record.search_document_id : record.id
30
31
  id.is_a?(Numeric) ? id : id.to_s
@@ -14,7 +14,7 @@ module Searchkick
14
14
  case mode
15
15
  when :async
16
16
  unless defined?(ActiveJob)
17
- raise Searchkick::Error, "Active Job not found"
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 Searchkick::Error, "Partial reindex not supported with queue option"
48
+ raise Error, "Partial reindex not supported with queue option"
49
49
  end
50
50
 
51
51
  index.reindex_queue.push_records(records)
@@ -5,7 +5,7 @@ module Searchkick
5
5
  def initialize(name)
6
6
  @name = name
7
7
 
8
- raise Searchkick::Error, "Searchkick.redis not set" unless Searchkick.redis
8
+ raise Error, "Searchkick.redis not set" unless Searchkick.redis
9
9
  end
10
10
 
11
11
  # supports single and multiple ids
@@ -141,7 +141,7 @@ module Searchkick
141
141
 
142
142
  def hits
143
143
  if error
144
- raise Searchkick::Error, "Query error - use the error method to view it"
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 Searchkick::Error, "Pass `scroll` option to the search method for scrolling" unless scroll_id
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
- Searchkick::Results.new(@klass, Searchkick.client.scroll(scroll: options[:scroll], body: {scroll_id: scroll_id}), @options)
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 Searchkick::Error, "Scroll id has expired"
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 Searchkick::Error, "Unknown model for index: #{index}. Pass the `models` option to the search method." unless models.any?
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
 
@@ -1,3 +1,3 @@
1
1
  module Searchkick
2
- VERSION = "5.0.0"
2
+ VERSION = "5.0.1"
3
3
  end
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
- Searchkick::Relation.new(klass, term, **options)
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
- Searchkick::MultiSearch.new(queries).perform
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 Searchkick::Error, "Redis not configured" unless redis
244
+ raise Error, "Redis not configured" unless redis
245
245
 
246
- batches_left = Searchkick::Index.new(index_name).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.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-22 00:00:00.000000000 Z
11
+ date: 2022-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel