searchkick 1.3.3 → 1.3.4

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
  SHA1:
3
- metadata.gz: 95d6fb192a6e28ebc711b99439f23ad5f27990ab
4
- data.tar.gz: 7b749691174ca6b03e471c75e4afb304f09869ef
3
+ metadata.gz: e771f2aea318aada5efd68350c101abca94a77a8
4
+ data.tar.gz: 4c3d8566133e79b6456609a9d50faf84be229454
5
5
  SHA512:
6
- metadata.gz: 37e07bcc09568bc7ca4806b5623eb53436fcdfcca773fd12398886240aefddb0666a5385d13146b7667fc582f9bedf6a9ce1193ecff4e7fe5c94484d9053fcf1
7
- data.tar.gz: 9a6d7f8844242656226dca9f2d984ee7740c43e3ccd0724a4bacb3f03b5426860140b1f5eebd554e70a6f9db42f008c92267b7b2c0c86a6d0057949c5ac26205
6
+ metadata.gz: 67375bbcd44840170e0fc29eeb84308f4e6814b24c30e8c8e6d0ed177df04dc038f7d0f4084d9cba19a2f5116249bb8313a37b01707e4163a83aeccc89a812c1
7
+ data.tar.gz: e31a38b61ed0ddf786f7aaf8be45eb39a938122305a9886d60fc33eaac335b267c468e1fb01511bf5863ca390bea86b216e822461422656e956c423948a3361c
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ## 1.3.4
2
+
3
+ - Added `resume` option to reindex
4
+ - Added search timeout to payload
5
+
1
6
  ## 1.3.3
2
7
 
3
8
  - Fix for namespaced models (broken in 1.3.2)
data/README.md CHANGED
@@ -372,6 +372,12 @@ class Product < ActiveRecord::Base
372
372
  end
373
373
  ```
374
374
 
375
+ If a reindex is interrupted, you can resume it with:
376
+
377
+ ```ruby
378
+ Product.reindex(resume: true)
379
+ ```
380
+
375
381
  ### To Reindex, or Not to Reindex
376
382
 
377
383
  #### Reindex
@@ -140,34 +140,60 @@ module Searchkick
140
140
  index
141
141
  end
142
142
 
143
- # remove old indices that start w/ index_name
144
- def clean_indices
145
- all_indices =
143
+ def all_indices(options = {})
144
+ indices =
146
145
  begin
147
146
  client.indices.get_aliases
148
147
  rescue Elasticsearch::Transport::Transport::Errors::NotFound
149
148
  {}
150
149
  end
151
- indices = all_indices.select { |k, v| (v.empty? || v["aliases"].empty?) && k =~ /\A#{Regexp.escape(name)}_\d{14,17}\z/ }.keys
150
+ indices = indices.select { |k, v| v.empty? || v["aliases"].empty? } if options[:unaliased]
151
+ indices.select { |k, v| k =~ /\A#{Regexp.escape(name)}_\d{14,17}\z/ }.keys
152
+ end
153
+
154
+ # remove old indices that start w/ index_name
155
+ def clean_indices
156
+ indices = all_indices(unaliased: true)
152
157
  indices.each do |index|
153
158
  Searchkick::Index.new(index).delete
154
159
  end
155
160
  indices
156
161
  end
157
162
 
163
+ def total_docs
164
+ response =
165
+ client.search(
166
+ index: name,
167
+ body: {
168
+ fields: [],
169
+ query: {match_all: {}},
170
+ size: 0
171
+ }
172
+ )
173
+
174
+ response["hits"]["total"]
175
+ end
176
+
158
177
  # https://gist.github.com/jarosan/3124884
159
178
  # http://www.elasticsearch.org/blog/changing-mapping-with-zero-downtime/
160
179
  def reindex_scope(scope, options = {})
161
180
  skip_import = options[:import] == false
181
+ resume = options[:resume]
162
182
 
163
- clean_indices
183
+ if resume
184
+ index_name = all_indices.sort.last
185
+ raise Searchkick::Error, "No index to resume" unless index_name
186
+ index = Searchkick::Index.new(index_name)
187
+ else
188
+ clean_indices
164
189
 
165
- index = create_index(index_options: scope.searchkick_index_options)
190
+ index = create_index(index_options: scope.searchkick_index_options)
191
+ end
166
192
 
167
193
  # check if alias exists
168
194
  if alias_exists?
169
195
  # import before swap
170
- index.import_scope(scope) unless skip_import
196
+ index.import_scope(scope, resume: resume) unless skip_import
171
197
 
172
198
  # get existing indices to remove
173
199
  swap(index.name)
@@ -177,7 +203,7 @@ module Searchkick
177
203
  swap(index.name)
178
204
 
179
205
  # import after swap
180
- index.import_scope(scope) unless skip_import
206
+ index.import_scope(scope, resume: resume) unless skip_import
181
207
  end
182
208
 
183
209
  index.refresh
@@ -185,12 +211,20 @@ module Searchkick
185
211
  true
186
212
  end
187
213
 
188
- def import_scope(scope)
214
+ def import_scope(scope, options = {})
189
215
  batch_size = @options[:batch_size] || 1000
190
216
 
191
217
  # use scope for import
192
218
  scope = scope.search_import if scope.respond_to?(:search_import)
193
219
  if scope.respond_to?(:find_in_batches)
220
+ if options[:resume]
221
+ # use total docs instead of max id since there's not a great way
222
+ # to get the max _id without scripting since it's a string
223
+
224
+ # TODO use primary key and prefix with table name
225
+ scope = scope.where("id > ?", total_docs)
226
+ end
227
+
194
228
  scope.find_in_batches batch_size: batch_size do |batch|
195
229
  import batch.select(&:should_index?)
196
230
  end
@@ -198,6 +232,7 @@ module Searchkick
198
232
  # https://github.com/karmi/tire/blob/master/lib/tire/model/import.rb
199
233
  # use cursor for Mongoid
200
234
  items = []
235
+ # TODO add resume
201
236
  scope.all.each do |item|
202
237
  items << item if item.should_index?
203
238
  if items.length == batch_size
@@ -368,6 +368,9 @@ module Searchkick
368
368
  # highlight
369
369
  set_highlights(payload, fields) if options[:highlight]
370
370
 
371
+ # timeout shortly after client times out
372
+ payload[:timeout] ||= "#{Searchkick.search_timeout + 1}s"
373
+
371
374
  # An empty array will cause only the _id and _type for each hit to be returned
372
375
  # doc for :select - http://www.elasticsearch.org/guide/reference/api/search/fields/
373
376
  # doc for :select_v2 - https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-source-filtering.html
@@ -1,3 +1,3 @@
1
1
  module Searchkick
2
- VERSION = "1.3.3"
2
+ VERSION = "1.3.4"
3
3
  end
data/test/query_test.rb CHANGED
@@ -13,11 +13,19 @@ class QueryTest < Minitest::Test
13
13
 
14
14
  def test_with_effective_min_score
15
15
  store_names ["Milk", "Milk2"]
16
- assert_equal ["Milk"], Product.search("Milk", body_options: { min_score: 0.1 }).map(&:name)
16
+ assert_search "milk", ["Milk"], body_options: {min_score: 0.1}
17
17
  end
18
18
 
19
19
  def test_with_uneffective_min_score
20
20
  store_names ["Milk", "Milk2"]
21
- assert_equal ["Milk", "Milk2"], Product.search("Milk", body_options: { min_score: 0.0001 }).map(&:name)
21
+ assert_search "milk", ["Milk", "Milk2"], body_options: {min_score: 0.0001}
22
+ end
23
+
24
+ def test_default_timeout
25
+ assert_equal "6s", Product.search("*", execute: false).body[:timeout]
26
+ end
27
+
28
+ def test_timeout_override
29
+ assert_equal "1s", Product.search("*", body_options: {timeout: "1s"}, execute: false).body[:timeout]
22
30
  end
23
31
  end
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: 1.3.3
4
+ version: 1.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kane
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-02 00:00:00.000000000 Z
11
+ date: 2016-08-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel