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 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