searchkick 5.5.2 → 6.0.0

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.
@@ -6,7 +6,7 @@ module Searchkick
6
6
  @index = index
7
7
  end
8
8
 
9
- def reindex(relation, mode:, method_name: nil, full: false, resume: false, scope: nil)
9
+ def reindex(relation, mode:, method_name: nil, ignore_missing: nil, full: false, resume: false, scope: nil, job_options: nil)
10
10
  # apply scopes
11
11
  if scope
12
12
  relation = relation.send(scope)
@@ -29,7 +29,7 @@ module Searchkick
29
29
  end
30
30
 
31
31
  if mode == :async && full
32
- return full_reindex_async(relation)
32
+ return full_reindex_async(relation, job_options: job_options)
33
33
  end
34
34
 
35
35
  relation = resume_relation(relation) if resume
@@ -37,7 +37,9 @@ module Searchkick
37
37
  reindex_options = {
38
38
  mode: mode,
39
39
  method_name: method_name,
40
- full: full
40
+ full: full,
41
+ ignore_missing: ignore_missing,
42
+ job_options: job_options
41
43
  }
42
44
  record_indexer = RecordIndexer.new(index)
43
45
 
@@ -128,23 +130,50 @@ module Searchkick
128
130
  @batch_size ||= index.options[:batch_size] || 1000
129
131
  end
130
132
 
131
- def full_reindex_async(relation)
133
+ def full_reindex_async(relation, job_options: nil)
132
134
  batch_id = 1
133
135
  class_name = relation.searchkick_options[:class_name]
136
+ starting_id = false
134
137
 
135
- in_batches(relation) do |items|
136
- batch_job(class_name, batch_id, items.map(&:id))
137
- batch_id += 1
138
+ if relation.respond_to?(:primary_key)
139
+ primary_key = relation.primary_key
140
+
141
+ starting_id =
142
+ begin
143
+ relation.minimum(primary_key)
144
+ rescue ActiveRecord::StatementInvalid
145
+ false
146
+ end
147
+ end
148
+
149
+ if starting_id.nil?
150
+ # no records, do nothing
151
+ elsif starting_id.is_a?(Numeric)
152
+ max_id = relation.maximum(primary_key)
153
+ batches_count = ((max_id - starting_id + 1) / batch_size.to_f).ceil
154
+
155
+ batches_count.times do |i|
156
+ min_id = starting_id + (i * batch_size)
157
+ batch_job(class_name, batch_id, job_options, min_id: min_id, max_id: min_id + batch_size - 1)
158
+ batch_id += 1
159
+ end
160
+ else
161
+ in_batches(relation) do |items|
162
+ batch_job(class_name, batch_id, job_options, record_ids: items.map(&:id).map { |v| v.instance_of?(Integer) ? v : v.to_s })
163
+ batch_id += 1
164
+ end
138
165
  end
139
166
  end
140
167
 
141
- def batch_job(class_name, batch_id, record_ids)
168
+ def batch_job(class_name, batch_id, job_options, **options)
169
+ job_options ||= {}
170
+ # TODO expire Redis key
142
171
  Searchkick.with_redis { |r| r.call("SADD", batches_key, [batch_id]) }
143
- Searchkick::BulkReindexJob.perform_later(
172
+ Searchkick::BulkReindexJob.set(**job_options).perform_later(
144
173
  class_name: class_name,
145
174
  index_name: index.name,
146
175
  batch_id: batch_id,
147
- record_ids: record_ids.map { |v| v.instance_of?(Integer) ? v : v.to_s }
176
+ **options
148
177
  )
149
178
  end
150
179
 
@@ -3,8 +3,7 @@ module Searchkick
3
3
  include Enumerable
4
4
  extend Forwardable
5
5
 
6
- # TODO remove klass and options in 6.0
7
- attr_reader :klass, :response, :options
6
+ attr_reader :response
8
7
 
9
8
  def_delegators :results, :each, :any?, :empty?, :size, :length, :slice, :[], :to_ary
10
9
 
@@ -14,11 +13,6 @@ module Searchkick
14
13
  @options = options
15
14
  end
16
15
 
17
- # TODO make private in 6.0
18
- def results
19
- @results ||= with_hit.map(&:first)
20
- end
21
-
22
16
  def with_hit
23
17
  return enum_for(:with_hit) unless block_given?
24
18
 
@@ -34,7 +28,7 @@ module Searchkick
34
28
  def suggestions
35
29
  if response["suggest"]
36
30
  response["suggest"].values.flat_map { |v| v.first["options"] }.sort_by { |o| -o["score"] }.map { |o| o["text"] }.uniq
37
- elsif options[:suggest] || options[:term] == "*" # TODO remove 2nd term
31
+ elsif options[:suggest]
38
32
  []
39
33
  else
40
34
  raise "Pass `suggest: true` to the search method for suggestions"
@@ -193,7 +187,12 @@ module Searchkick
193
187
  else
194
188
  begin
195
189
  # TODO Active Support notifications for this scroll call
196
- Results.new(@klass, Searchkick.client.scroll(scroll: options[:scroll], body: {scroll_id: scroll_id}), @options)
190
+ params = {
191
+ scroll: options[:scroll],
192
+ body: {scroll_id: scroll_id}
193
+ }
194
+ params[:opaque_id] = options[:opaque_id] if options[:opaque_id]
195
+ Results.new(@klass, Searchkick.client.scroll(params), @options)
197
196
  rescue => e
198
197
  if Searchkick.not_found_error?(e) && e.message =~ /search_context_missing_exception/i
199
198
  raise Error, "Scroll id has expired"
@@ -217,6 +216,12 @@ module Searchkick
217
216
 
218
217
  private
219
218
 
219
+ attr_reader :klass, :options
220
+
221
+ def results
222
+ @results ||= with_hit.map(&:first)
223
+ end
224
+
220
225
  def with_hit_and_missing_records
221
226
  @with_hit_and_missing_records ||= begin
222
227
  missing_records = []
@@ -1,3 +1,3 @@
1
1
  module Searchkick
2
- VERSION = "5.5.2"
2
+ VERSION = "6.0.0"
3
3
  end
data/lib/searchkick.rb CHANGED
@@ -3,8 +3,9 @@ require "active_support"
3
3
  require "active_support/core_ext/hash/deep_merge"
4
4
  require "active_support/core_ext/module/attr_internal"
5
5
  require "active_support/core_ext/module/delegation"
6
+ require "active_support/deprecation"
7
+ require "active_support/log_subscriber"
6
8
  require "active_support/notifications"
7
- require "hashie"
8
9
 
9
10
  # stdlib
10
11
  require "forwardable"
@@ -49,7 +50,7 @@ module Searchkick
49
50
  class MissingIndexError < Error; end
50
51
  class UnsupportedVersionError < Error
51
52
  def message
52
- "This version of Searchkick requires Elasticsearch 7+ or OpenSearch 1+"
53
+ "This version of Searchkick requires Elasticsearch 8+ or OpenSearch 2+"
53
54
  end
54
55
  end
55
56
  class InvalidQueryError < Error; end
@@ -57,7 +58,7 @@ module Searchkick
57
58
  class ImportError < Error; end
58
59
 
59
60
  class << self
60
- attr_accessor :search_method_name, :timeout, :models, :client_options, :redis, :index_prefix, :index_suffix, :queue_name, :model_options, :client_type
61
+ attr_accessor :search_method_name, :timeout, :models, :client_options, :redis, :index_prefix, :index_suffix, :queue_name, :model_options, :client_type, :parent_job
61
62
  attr_writer :client, :env, :search_timeout
62
63
  attr_reader :aws_credentials
63
64
  end
@@ -67,6 +68,7 @@ module Searchkick
67
68
  self.client_options = {}
68
69
  self.queue_name = :searchkick
69
70
  self.model_options = {}
71
+ self.parent_job = "ActiveJob::Base"
70
72
 
71
73
  def self.client
72
74
  @client ||= begin
@@ -83,34 +85,21 @@ module Searchkick
83
85
  raise Error, "No client found - install the `elasticsearch` or `opensearch-ruby` gem"
84
86
  end
85
87
 
86
- # check after client to ensure faraday is installed
87
- # TODO remove in Searchkick 6
88
- if defined?(Typhoeus) && Gem::Version.new(Faraday::VERSION) < Gem::Version.new("0.14.0")
89
- require "typhoeus/adapters/faraday"
90
- end
91
-
92
88
  if client_type == :opensearch
93
89
  OpenSearch::Client.new({
94
90
  url: ENV["OPENSEARCH_URL"],
95
- # TODO remove headers in Searchkick 6
96
- transport_options: {request: {timeout: timeout}, headers: {content_type: "application/json"}},
91
+ transport_options: {request: {timeout: timeout}},
97
92
  retry_on_failure: 2
98
93
  }.deep_merge(client_options)) do |f|
99
94
  f.use Searchkick::Middleware
100
95
  f.request :aws_sigv4, signer_middleware_aws_params if aws_credentials
101
96
  end
102
97
  else
103
- raise Error, "The `elasticsearch` gem must be 7+" if Elasticsearch::VERSION.to_i < 7
104
-
105
- transport_options = {request: {timeout: timeout}}
106
- # TODO remove headers in Searchkick 6
107
- if Elasticsearch::VERSION.to_i < 9
108
- transport_options[:headers] = {content_type: "application/json"}
109
- end
98
+ raise Error, "The `elasticsearch` gem must be 8+" if Elasticsearch::VERSION.to_i < 8
110
99
 
111
100
  Elasticsearch::Client.new({
112
101
  url: ENV["ELASTICSEARCH_URL"],
113
- transport_options: transport_options,
102
+ transport_options: {request: {timeout: timeout}},
114
103
  retry_on_failure: 2
115
104
  }.deep_merge(client_options)) do |f|
116
105
  f.use Searchkick::Middleware
@@ -144,16 +133,14 @@ module Searchkick
144
133
  @opensearch
145
134
  end
146
135
 
147
- # TODO always check true version in Searchkick 6
148
- def self.server_below?(version, true_version = false)
149
- server_version = !true_version && opensearch? ? "7.10.2" : self.server_version
136
+ def self.server_below?(version)
150
137
  Gem::Version.new(server_version.split("-")[0]) < Gem::Version.new(version.split("-")[0])
151
138
  end
152
139
 
153
140
  # private
154
141
  def self.knn_support?
155
142
  if opensearch?
156
- !server_below?("2.4.0", true)
143
+ !server_below?("2.4.0")
157
144
  else
158
145
  !server_below?("8.6.0")
159
146
  end
@@ -184,17 +171,11 @@ module Searchkick
184
171
  end
185
172
  end
186
173
 
187
- # TODO remove in Searchkick 6
188
- if options[:execute] == false
189
- Searchkick.warn("The execute option is no longer needed")
190
- options.delete(:execute)
191
- end
192
-
193
174
  options = options.merge(block: block) if block
194
175
  Relation.new(klass, term, **options)
195
176
  end
196
177
 
197
- def self.multi_search(queries)
178
+ def self.multi_search(queries, opaque_id: nil)
198
179
  return if queries.empty?
199
180
 
200
181
  queries = queries.map { |q| q.send(:query) }
@@ -203,7 +184,7 @@ module Searchkick
203
184
  body: queries.flat_map { |q| [q.params.except(:body).to_json, q.body.to_json] }.map { |v| "#{v}\n" }.join
204
185
  }
205
186
  ActiveSupport::Notifications.instrument("multi_search.searchkick", event) do
206
- MultiSearch.new(queries).perform
187
+ MultiSearch.new(queries, opaque_id: opaque_id).perform
207
188
  end
208
189
  end
209
190
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: searchkick
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.5.2
4
+ version: 6.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
@@ -15,28 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '7.1'
18
+ version: '7.2'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: '7.1'
26
- - !ruby/object:Gem::Dependency
27
- name: hashie
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: '0'
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: '0'
25
+ version: '7.2'
40
26
  email: andrew@ankane.org
41
27
  executables: []
42
28
  extensions: []
@@ -91,7 +77,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
77
  - !ruby/object:Gem::Version
92
78
  version: '0'
93
79
  requirements: []
94
- rubygems_version: 3.6.7
80
+ rubygems_version: 3.6.9
95
81
  specification_version: 4
96
82
  summary: Intelligent search made easy with Rails and Elasticsearch or OpenSearch
97
83
  test_files: []