Commit 015990014a645f4a164128b4956c81dd6c81676f

Authored by Andrew Kane
1 parent 84c52170

Added partial_reindex method - closes #766

1 ## 1.4.1 [unreleased] 1 ## 1.4.1 [unreleased]
2 2
  3 +- Added `partial_reindex` method
3 - Added `debug` option to `search` method 4 - Added `debug` option to `search` method
4 5
5 ## 1.4.0 6 ## 1.4.0
@@ -1213,6 +1213,18 @@ Product.where("id > 100000").find_in_batches do |batch| @@ -1213,6 +1213,18 @@ Product.where("id > 100000").find_in_batches do |batch|
1213 end 1213 end
1214 ``` 1214 ```
1215 1215
  1216 +Reindex a subset of attributes [master]
  1217 +
  1218 +```ruby
  1219 +class Product < ActiveRecord::Base
  1220 + def search_prices
  1221 + {price: price}
  1222 + end
  1223 +end
  1224 +
  1225 +Product.partial_reindex(:search_prices)
  1226 +```
  1227 +
1216 Remove old indices 1228 Remove old indices
1217 1229
1218 ```ruby 1230 ```ruby
lib/searchkick/index.rb
@@ -67,6 +67,10 @@ module Searchkick @@ -67,6 +67,10 @@ module Searchkick
67 end 67 end
68 alias_method :import, :bulk_index 68 alias_method :import, :bulk_index
69 69
  70 + def bulk_update(records, method_name)
  71 + Searchkick.queue_items(records.map { |r| {update: record_data(r).merge(data: {doc: search_data(r, method_name)})} })
  72 + end
  73 +
70 def record_data(r) 74 def record_data(r)
71 data = { 75 data = {
72 _index: name, 76 _index: name,
@@ -221,6 +225,7 @@ module Searchkick @@ -221,6 +225,7 @@ module Searchkick
221 225
222 def import_scope(scope, options = {}) 226 def import_scope(scope, options = {})
223 batch_size = @options[:batch_size] || 1000 227 batch_size = @options[:batch_size] || 1000
  228 + method_name = options[:method_name]
224 229
225 # use scope for import 230 # use scope for import
226 scope = scope.search_import if scope.respond_to?(:search_import) 231 scope = scope.search_import if scope.respond_to?(:search_import)
@@ -234,7 +239,7 @@ module Searchkick @@ -234,7 +239,7 @@ module Searchkick
234 end 239 end
235 240
236 scope.find_in_batches batch_size: batch_size do |batch| 241 scope.find_in_batches batch_size: batch_size do |batch|
237 - import batch.select(&:should_index?) 242 + import_or_update batch.select(&:should_index?), method_name
238 end 243 end
239 else 244 else
240 # https://github.com/karmi/tire/blob/master/lib/tire/model/import.rb 245 # https://github.com/karmi/tire/blob/master/lib/tire/model/import.rb
@@ -244,14 +249,18 @@ module Searchkick @@ -244,14 +249,18 @@ module Searchkick
244 scope.all.each do |item| 249 scope.all.each do |item|
245 items << item if item.should_index? 250 items << item if item.should_index?
246 if items.length == batch_size 251 if items.length == batch_size
247 - import items 252 + import_or_update items, method_name
248 items = [] 253 items = []
249 end 254 end
250 end 255 end
251 - import items 256 + import_or_update items, method_name
252 end 257 end
253 end 258 end
254 259
  260 + def import_or_update(records, method_name)
  261 + method_name ? bulk_update(records, method_name) : import(records)
  262 + end
  263 +
255 # other 264 # other
256 265
257 def tokens(text, options = {}) 266 def tokens(text, options = {})
@@ -285,8 +294,9 @@ module Searchkick @@ -285,8 +294,9 @@ module Searchkick
285 id.is_a?(Numeric) ? id : id.to_s 294 id.is_a?(Numeric) ? id : id.to_s
286 end 295 end
287 296
288 - def search_data(record)  
289 - source = record.search_data 297 + def search_data(record, method_name = nil)
  298 + partial_reindex = !method_name.nil?
  299 + source = record.send(method_name || :search_data)
290 options = record.class.searchkick_options 300 options = record.class.searchkick_options
291 301
292 # stringify fields 302 # stringify fields
@@ -302,7 +312,7 @@ module Searchkick @@ -302,7 +312,7 @@ module Searchkick
302 312
303 # hack to prevent generator field doesn't exist error 313 # hack to prevent generator field doesn't exist error
304 (options[:suggest] || []).map(&:to_s).each do |field| 314 (options[:suggest] || []).map(&:to_s).each do |field|
305 - source[field] = nil unless source[field] 315 + source[field] = nil if !source[field] && !partial_reindex
306 end 316 end
307 317
308 # locations 318 # locations
lib/searchkick/model.rb
@@ -54,6 +54,13 @@ module Searchkick @@ -54,6 +54,13 @@ module Searchkick
54 end 54 end
55 alias_method :reindex, :searchkick_reindex unless method_defined?(:reindex) 55 alias_method :reindex, :searchkick_reindex unless method_defined?(:reindex)
56 56
  57 + def searchkick_partial_reindex(method_name)
  58 + searchkick_index.import_scope(searchkick_klass, method_name: method_name)
  59 + searchkick_index.refresh
  60 + true
  61 + end
  62 + alias_method :partial_reindex, :searchkick_partial_reindex unless method_defined?(:partial_reindex)
  63 +
57 def clean_indices 64 def clean_indices
58 searchkick_index.clean_indices 65 searchkick_index.clean_indices
59 end 66 end
test/partial_reindex_test.rb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +require_relative "test_helper"
  2 +
  3 +class PartialReindexTest < Minitest::Test
  4 + def test_basic
  5 + store [{name: "Hi", color: "Blue"}]
  6 +
  7 + # normal search
  8 + assert_search "hi", ["Hi"], fields: [:name], load: false
  9 + assert_search "blue", ["Hi"], fields: [:color], load: false
  10 +
  11 + # update
  12 + Product.first.update_column :name, "Bye"
  13 + Product.first.update_column :color, "Red"
  14 + Product.searchkick_index.refresh
  15 +
  16 + # index not updated
  17 + assert_search "hi", ["Hi"], fields: [:name], load: false
  18 + assert_search "blue", ["Hi"], fields: [:color], load: false
  19 +
  20 + # partial reindex
  21 + Product.partial_reindex(:search_name)
  22 +
  23 + # name updated, but not color
  24 + assert_search "bye", ["Bye"], fields: [:name], load: false
  25 + assert_search "blue", ["Bye"], fields: [:color], load: false
  26 + end
  27 +end
test/test_helper.rb
@@ -309,6 +309,12 @@ class Product @@ -309,6 +309,12 @@ class Product
309 def should_index? 309 def should_index?
310 name != "DO NOT INDEX" 310 name != "DO NOT INDEX"
311 end 311 end
  312 +
  313 + def search_name
  314 + {
  315 + name: name
  316 + }
  317 + end
312 end 318 end
313 319
314 class Store 320 class Store