searchkick 4.6.3 → 5.0.2
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 +4 -4
- data/CHANGELOG.md +35 -1
- data/README.md +187 -124
- data/lib/searchkick/bulk_reindex_job.rb +12 -8
- data/lib/searchkick/controller_runtime.rb +40 -0
- data/lib/searchkick/index.rb +146 -65
- data/lib/searchkick/index_cache.rb +30 -0
- data/lib/searchkick/index_options.rb +17 -67
- data/lib/searchkick/indexer.rb +15 -8
- data/lib/searchkick/log_subscriber.rb +57 -0
- data/lib/searchkick/middleware.rb +1 -1
- data/lib/searchkick/model.rb +48 -49
- data/lib/searchkick/process_batch_job.rb +9 -25
- data/lib/searchkick/process_queue_job.rb +3 -2
- data/lib/searchkick/query.rb +38 -54
- data/lib/searchkick/record_data.rb +1 -1
- data/lib/searchkick/record_indexer.rb +136 -52
- data/lib/searchkick/reindex_queue.rb +26 -3
- data/lib/searchkick/reindex_v2_job.rb +10 -34
- data/lib/searchkick/relation.rb +112 -0
- data/lib/searchkick/relation_indexer.rb +150 -0
- data/lib/searchkick/results.rb +27 -28
- data/lib/searchkick/version.rb +1 -1
- data/lib/searchkick.rb +159 -84
- data/lib/tasks/searchkick.rake +6 -3
- metadata +11 -28
- data/lib/searchkick/bulk_indexer.rb +0 -173
- data/lib/searchkick/logging.rb +0 -246
@@ -0,0 +1,57 @@
|
|
1
|
+
# based on https://gist.github.com/mnutt/566725
|
2
|
+
module Searchkick
|
3
|
+
class LogSubscriber < ActiveSupport::LogSubscriber
|
4
|
+
def self.runtime=(value)
|
5
|
+
Thread.current[:searchkick_runtime] = value
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.runtime
|
9
|
+
Thread.current[:searchkick_runtime] ||= 0
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.reset_runtime
|
13
|
+
rt = runtime
|
14
|
+
self.runtime = 0
|
15
|
+
rt
|
16
|
+
end
|
17
|
+
|
18
|
+
def search(event)
|
19
|
+
self.class.runtime += event.duration
|
20
|
+
return unless logger.debug?
|
21
|
+
|
22
|
+
payload = event.payload
|
23
|
+
name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
|
24
|
+
|
25
|
+
index = payload[:query][:index].is_a?(Array) ? payload[:query][:index].join(",") : payload[:query][:index]
|
26
|
+
type = payload[:query][:type]
|
27
|
+
request_params = payload[:query].except(:index, :type, :body)
|
28
|
+
|
29
|
+
params = []
|
30
|
+
request_params.each do |k, v|
|
31
|
+
params << "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"
|
32
|
+
end
|
33
|
+
|
34
|
+
debug " #{color(name, YELLOW, true)} #{index}#{type ? "/#{type.join(',')}" : ''}/_search#{params.any? ? '?' + params.join('&') : nil} #{payload[:query][:body].to_json}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def request(event)
|
38
|
+
self.class.runtime += event.duration
|
39
|
+
return unless logger.debug?
|
40
|
+
|
41
|
+
payload = event.payload
|
42
|
+
name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
|
43
|
+
|
44
|
+
debug " #{color(name, YELLOW, true)} #{payload.except(:name).to_json}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def multi_search(event)
|
48
|
+
self.class.runtime += event.duration
|
49
|
+
return unless logger.debug?
|
50
|
+
|
51
|
+
payload = event.payload
|
52
|
+
name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
|
53
|
+
|
54
|
+
debug " #{color(name, YELLOW, true)} _msearch #{payload[:body]}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/searchkick/model.rb
CHANGED
@@ -7,7 +7,7 @@ module Searchkick
|
|
7
7
|
:filterable, :geo_shape, :highlight, :ignore_above, :index_name, :index_prefix, :inheritance, :language,
|
8
8
|
:locations, :mappings, :match, :merge_mappings, :routing, :searchable, :search_synonyms, :settings, :similarity,
|
9
9
|
:special_characters, :stem, :stemmer, :stem_conversions, :stem_exclusion, :stemmer_override, :suggest, :synonyms, :text_end,
|
10
|
-
:text_middle, :text_start, :
|
10
|
+
:text_middle, :text_start, :unscope, :word, :word_end, :word_middle, :word_start]
|
11
11
|
raise ArgumentError, "unknown keywords: #{unknown_keywords.join(", ")}" if unknown_keywords.any?
|
12
12
|
|
13
13
|
raise "Only call searchkick once per model" if respond_to?(:searchkick_index)
|
@@ -22,52 +22,78 @@ module Searchkick
|
|
22
22
|
raise ArgumentError, "Invalid value for callbacks"
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
25
|
+
base = self
|
26
|
+
|
27
|
+
mod = Module.new
|
28
|
+
include(mod)
|
29
|
+
mod.module_eval do
|
30
|
+
def reindex(method_name = nil, mode: nil, refresh: false)
|
31
|
+
self.class.searchkick_index.reindex([self], method_name: method_name, mode: mode, refresh: refresh, single: true)
|
32
|
+
end unless base.method_defined?(:reindex)
|
33
|
+
|
34
|
+
def similar(**options)
|
35
|
+
self.class.searchkick_index.similar_record(self, **options)
|
36
|
+
end unless base.method_defined?(:similar)
|
37
|
+
|
38
|
+
def search_data
|
39
|
+
data = respond_to?(:to_hash) ? to_hash : serializable_hash
|
40
|
+
data.delete("id")
|
41
|
+
data.delete("_id")
|
42
|
+
data.delete("_type")
|
43
|
+
data
|
44
|
+
end unless base.method_defined?(:search_data)
|
45
|
+
|
46
|
+
def should_index?
|
47
|
+
true
|
48
|
+
end unless base.method_defined?(:should_index?)
|
49
|
+
end
|
33
50
|
|
34
51
|
class_eval do
|
35
|
-
cattr_reader :searchkick_options, :searchkick_klass
|
52
|
+
cattr_reader :searchkick_options, :searchkick_klass, instance_reader: false
|
36
53
|
|
37
54
|
class_variable_set :@@searchkick_options, options.dup
|
38
55
|
class_variable_set :@@searchkick_klass, self
|
39
|
-
class_variable_set :@@
|
40
|
-
class_variable_set :@@searchkick_index_cache, {}
|
56
|
+
class_variable_set :@@searchkick_index_cache, Searchkick::IndexCache.new
|
41
57
|
|
42
58
|
class << self
|
43
59
|
def searchkick_search(term = "*", **options, &block)
|
44
|
-
|
45
|
-
|
60
|
+
if Searchkick.relation?(self)
|
61
|
+
raise Searchkick::Error, "search must be called on model, not relation"
|
62
|
+
end
|
46
63
|
|
47
64
|
Searchkick.search(term, model: self, **options, &block)
|
48
65
|
end
|
49
66
|
alias_method Searchkick.search_method_name, :searchkick_search if Searchkick.search_method_name
|
50
67
|
|
51
68
|
def searchkick_index(name: nil)
|
52
|
-
|
53
|
-
|
69
|
+
index_name = name || searchkick_index_name
|
70
|
+
index_name = index_name.call if index_name.respond_to?(:call)
|
54
71
|
index_cache = class_variable_get(:@@searchkick_index_cache)
|
55
|
-
index_cache
|
72
|
+
index_cache.fetch(index_name) { Searchkick::Index.new(index_name, searchkick_options) }
|
56
73
|
end
|
57
74
|
alias_method :search_index, :searchkick_index unless method_defined?(:search_index)
|
58
75
|
|
59
76
|
def searchkick_reindex(method_name = nil, **options)
|
60
|
-
|
61
|
-
relation = (respond_to?(:current_scope) && respond_to?(:default_scoped) && current_scope && current_scope.to_sql != default_scoped.to_sql) ||
|
62
|
-
(respond_to?(:queryable) && queryable != unscoped.with_default_scope)
|
63
|
-
|
64
|
-
searchkick_index.reindex(searchkick_klass, method_name, scoped: relation, **options)
|
77
|
+
searchkick_index.reindex(self, method_name: method_name, **options)
|
65
78
|
end
|
66
79
|
alias_method :reindex, :searchkick_reindex unless method_defined?(:reindex)
|
67
80
|
|
68
81
|
def searchkick_index_options
|
69
82
|
searchkick_index.index_options
|
70
83
|
end
|
84
|
+
|
85
|
+
def searchkick_index_name
|
86
|
+
@searchkick_index_name ||= begin
|
87
|
+
options = class_variable_get(:@@searchkick_options)
|
88
|
+
if options[:index_name]
|
89
|
+
options[:index_name]
|
90
|
+
elsif options[:index_prefix].respond_to?(:call)
|
91
|
+
-> { [options[:index_prefix].call, searchkick_klass.model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_") }
|
92
|
+
else
|
93
|
+
[options.key?(:index_prefix) ? options[:index_prefix] : Searchkick.index_prefix, searchkick_klass.model_name.plural, Searchkick.env, Searchkick.index_suffix].compact.join("_")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
71
97
|
end
|
72
98
|
|
73
99
|
# always add callbacks, even when callbacks is false
|
@@ -78,33 +104,6 @@ module Searchkick
|
|
78
104
|
after_save :reindex, if: -> { Searchkick.callbacks?(default: callbacks) }
|
79
105
|
after_destroy :reindex, if: -> { Searchkick.callbacks?(default: callbacks) }
|
80
106
|
end
|
81
|
-
|
82
|
-
def reindex(method_name = nil, **options)
|
83
|
-
RecordIndexer.new(self).reindex(method_name, **options)
|
84
|
-
end unless method_defined?(:reindex)
|
85
|
-
|
86
|
-
# TODO switch to keyword arguments
|
87
|
-
def similar(options = {})
|
88
|
-
self.class.searchkick_index.similar_record(self, **options)
|
89
|
-
end unless method_defined?(:similar)
|
90
|
-
|
91
|
-
def search_data
|
92
|
-
data = respond_to?(:to_hash) ? to_hash : serializable_hash
|
93
|
-
data.delete("id")
|
94
|
-
data.delete("_id")
|
95
|
-
data.delete("_type")
|
96
|
-
data
|
97
|
-
end unless method_defined?(:search_data)
|
98
|
-
|
99
|
-
def should_index?
|
100
|
-
true
|
101
|
-
end unless method_defined?(:should_index?)
|
102
|
-
|
103
|
-
if defined?(Cequel) && self < Cequel::Record && !method_defined?(:destroyed?)
|
104
|
-
def destroyed?
|
105
|
-
transient?
|
106
|
-
end
|
107
|
-
end
|
108
107
|
end
|
109
108
|
end
|
110
109
|
end
|
@@ -3,34 +3,18 @@ module Searchkick
|
|
3
3
|
queue_as { Searchkick.queue_name }
|
4
4
|
|
5
5
|
def perform(class_name:, record_ids:, index_name: nil)
|
6
|
-
|
7
|
-
|
8
|
-
record_ids = routing.keys
|
6
|
+
model = Searchkick.load_model(class_name)
|
7
|
+
index = model.searchkick_index(name: index_name)
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
# determine which records to delete
|
16
|
-
delete_ids = record_ids - records.map { |r| r.id.to_s }
|
17
|
-
delete_records = delete_ids.map do |id|
|
18
|
-
m = klass.new
|
19
|
-
m.id = id
|
20
|
-
if routing[id]
|
21
|
-
m.define_singleton_method(:search_routing) do
|
22
|
-
routing[id]
|
23
|
-
end
|
9
|
+
items =
|
10
|
+
record_ids.map do |r|
|
11
|
+
parts = r.split(/(?<!\|)\|(?!\|)/, 2)
|
12
|
+
.map { |v| v.gsub("||", "|") }
|
13
|
+
{id: parts[0], routing: parts[1]}
|
24
14
|
end
|
25
|
-
m
|
26
|
-
end
|
27
15
|
|
28
|
-
|
29
|
-
index
|
30
|
-
Searchkick.callbacks(:bulk) do
|
31
|
-
index.bulk_index(records) if records.any?
|
32
|
-
index.bulk_delete(delete_records) if delete_records.any?
|
33
|
-
end
|
16
|
+
relation = Searchkick.scope(model)
|
17
|
+
RecordIndexer.new(index).reindex_items(relation, items, method_name: nil)
|
34
18
|
end
|
35
19
|
end
|
36
20
|
end
|
@@ -3,11 +3,12 @@ module Searchkick
|
|
3
3
|
queue_as { Searchkick.queue_name }
|
4
4
|
|
5
5
|
def perform(class_name:, index_name: nil, inline: false)
|
6
|
-
model = class_name
|
6
|
+
model = Searchkick.load_model(class_name)
|
7
|
+
index = model.searchkick_index(name: index_name)
|
7
8
|
limit = model.searchkick_options[:batch_size] || 1000
|
8
9
|
|
9
10
|
loop do
|
10
|
-
record_ids =
|
11
|
+
record_ids = index.reindex_queue.reserve(limit: limit)
|
11
12
|
if record_ids.any?
|
12
13
|
batch_options = {
|
13
14
|
class_name: class_name,
|
data/lib/searchkick/query.rb
CHANGED
@@ -18,7 +18,7 @@ module Searchkick
|
|
18
18
|
|
19
19
|
def initialize(klass, term = "*", **options)
|
20
20
|
unknown_keywords = options.keys - [:aggs, :block, :body, :body_options, :boost,
|
21
|
-
:boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :
|
21
|
+
:boost_by, :boost_by_distance, :boost_by_recency, :boost_where, :conversions, :conversions_term, :debug, :emoji, :exclude, :explain,
|
22
22
|
:fields, :highlight, :includes, :index_name, :indices_boost, :limit, :load,
|
23
23
|
:match, :misspellings, :models, :model_includes, :offset, :operator, :order, :padding, :page, :per_page, :profile,
|
24
24
|
:request_params, :routing, :scope_results, :scroll, :select, :similar, :smart_aggs, :suggest, :total_entries, :track, :type, :where]
|
@@ -148,9 +148,6 @@ module Searchkick
|
|
148
148
|
}
|
149
149
|
|
150
150
|
if options[:debug]
|
151
|
-
# can remove when minimum Ruby version is 2.5
|
152
|
-
require "pp"
|
153
|
-
|
154
151
|
puts "Searchkick Version: #{Searchkick::VERSION}"
|
155
152
|
puts "Elasticsearch Version: #{Searchkick.server_version}"
|
156
153
|
puts
|
@@ -190,11 +187,11 @@ module Searchkick
|
|
190
187
|
end
|
191
188
|
|
192
189
|
# set execute for multi search
|
193
|
-
@execute =
|
190
|
+
@execute = Results.new(searchkick_klass, response, opts)
|
194
191
|
end
|
195
192
|
|
196
193
|
def retry_misspellings?(response)
|
197
|
-
@misspellings_below &&
|
194
|
+
@misspellings_below && Results.new(searchkick_klass, response).total_count < @misspellings_below
|
198
195
|
end
|
199
196
|
|
200
197
|
private
|
@@ -210,14 +207,14 @@ module Searchkick
|
|
210
207
|
e.message.include?("No query registered for [function_score]")
|
211
208
|
)
|
212
209
|
|
213
|
-
raise UnsupportedVersionError
|
210
|
+
raise UnsupportedVersionError
|
214
211
|
elsif status_code == 400
|
215
212
|
if (
|
216
213
|
e.message.include?("bool query does not support [filter]") ||
|
217
214
|
e.message.include?("[bool] filter does not support [filter]")
|
218
215
|
)
|
219
216
|
|
220
|
-
raise UnsupportedVersionError
|
217
|
+
raise UnsupportedVersionError
|
221
218
|
elsif e.message =~ /analyzer \[searchkick_.+\] not found/
|
222
219
|
raise InvalidQueryError, "Bad mapping - run #{reindex_command}"
|
223
220
|
else
|
@@ -233,7 +230,14 @@ module Searchkick
|
|
233
230
|
end
|
234
231
|
|
235
232
|
def execute_search
|
236
|
-
|
233
|
+
name = searchkick_klass ? "#{searchkick_klass.name} Search" : "Search"
|
234
|
+
event = {
|
235
|
+
name: name,
|
236
|
+
query: params
|
237
|
+
}
|
238
|
+
ActiveSupport::Notifications.instrument("search.searchkick", event) do
|
239
|
+
Searchkick.client.search(params)
|
240
|
+
end
|
237
241
|
end
|
238
242
|
|
239
243
|
def prepare
|
@@ -268,9 +272,10 @@ module Searchkick
|
|
268
272
|
should = []
|
269
273
|
|
270
274
|
if options[:similar]
|
275
|
+
like = options[:similar] == true ? term : options[:similar]
|
271
276
|
query = {
|
272
277
|
more_like_this: {
|
273
|
-
like:
|
278
|
+
like: like,
|
274
279
|
min_doc_freq: 1,
|
275
280
|
min_term_freq: 1,
|
276
281
|
analyzer: "searchkick_search2"
|
@@ -383,11 +388,6 @@ module Searchkick
|
|
383
388
|
|
384
389
|
if field.start_with?("*.")
|
385
390
|
q2 = qs.map { |q| {multi_match: q.merge(fields: [field], type: match_type == :match_phrase ? "phrase" : "best_fields")} }
|
386
|
-
if below61?
|
387
|
-
q2.each do |q|
|
388
|
-
q[:multi_match].delete(:fuzzy_transpositions)
|
389
|
-
end
|
390
|
-
end
|
391
391
|
else
|
392
392
|
q2 = qs.map { |q| {match_type => {field => q}} }
|
393
393
|
end
|
@@ -439,7 +439,7 @@ module Searchkick
|
|
439
439
|
payload = {}
|
440
440
|
|
441
441
|
# type when inheritance
|
442
|
-
where = (options[:where] || {}).dup
|
442
|
+
where = ensure_permitted(options[:where] || {}).dup
|
443
443
|
if searchkick_options[:inheritance] && (options[:type] || (klass != searchkick_klass && searchkick_index))
|
444
444
|
where[:type] = [options[:type] || klass].flatten.map { |v| searchkick_index.klass_document_type(v, true) }
|
445
445
|
end
|
@@ -696,9 +696,9 @@ module Searchkick
|
|
696
696
|
def set_boost_by(multiply_filters, custom_filters)
|
697
697
|
boost_by = options[:boost_by] || {}
|
698
698
|
if boost_by.is_a?(Array)
|
699
|
-
boost_by =
|
699
|
+
boost_by = boost_by.to_h { |f| [f, {factor: 1}] }
|
700
700
|
elsif boost_by.is_a?(Hash)
|
701
|
-
multiply_by, boost_by = boost_by.partition { |_, v| v.delete(:boost_mode) == "multiply" }.map
|
701
|
+
multiply_by, boost_by = boost_by.partition { |_, v| v.delete(:boost_mode) == "multiply" }.map(&:to_h)
|
702
702
|
end
|
703
703
|
boost_by[options[:boost]] = {factor: 1} if options[:boost]
|
704
704
|
|
@@ -763,7 +763,7 @@ module Searchkick
|
|
763
763
|
|
764
764
|
def set_highlights(payload, fields)
|
765
765
|
payload[:highlight] = {
|
766
|
-
fields:
|
766
|
+
fields: fields.to_h { |f| [f, {}] },
|
767
767
|
fragment_size: 0
|
768
768
|
}
|
769
769
|
|
@@ -797,7 +797,7 @@ module Searchkick
|
|
797
797
|
aggs = options[:aggs]
|
798
798
|
payload[:aggs] = {}
|
799
799
|
|
800
|
-
aggs =
|
800
|
+
aggs = aggs.to_h { |f| [f, {}] } if aggs.is_a?(Array) # convert to more advanced syntax
|
801
801
|
aggs.each do |field, agg_options|
|
802
802
|
size = agg_options[:limit] ? agg_options[:limit] : 1_000
|
803
803
|
shared_agg_options = agg_options.except(:limit, :field, :ranges, :date_ranges, :where)
|
@@ -836,8 +836,9 @@ module Searchkick
|
|
836
836
|
end
|
837
837
|
|
838
838
|
where = {}
|
839
|
-
where = (options[:where] || {}).reject { |k| k == field } unless options[:smart_aggs] == false
|
840
|
-
|
839
|
+
where = ensure_permitted(options[:where] || {}).reject { |k| k == field } unless options[:smart_aggs] == false
|
840
|
+
agg_where = ensure_permitted(agg_options[:where] || {})
|
841
|
+
agg_filters = where_filters(where.merge(agg_where))
|
841
842
|
|
842
843
|
# only do one level comparison for simplicity
|
843
844
|
filters.select! do |filter|
|
@@ -873,19 +874,16 @@ module Searchkick
|
|
873
874
|
end
|
874
875
|
|
875
876
|
def set_order(payload)
|
876
|
-
|
877
|
-
id_field = :_id
|
878
|
-
# TODO no longer map id to _id in Searchkick 5
|
879
|
-
# since sorting on _id is deprecated in Elasticsearch
|
880
|
-
payload[:sort] = order.is_a?(Array) ? order : Hash[order.map { |k, v| [k.to_s == "id" ? id_field : k, v] }]
|
877
|
+
payload[:sort] = options[:order].is_a?(Enumerable) ? options[:order] : {options[:order] => :asc}
|
881
878
|
end
|
882
879
|
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
880
|
+
# provides *very* basic protection from unfiltered parameters
|
881
|
+
# this is not meant to be comprehensive and may be expanded in the future
|
882
|
+
def ensure_permitted(obj)
|
883
|
+
obj.to_h
|
884
|
+
end
|
888
885
|
|
886
|
+
def where_filters(where)
|
889
887
|
filters = []
|
890
888
|
(where || {}).each do |field, value|
|
891
889
|
field = :_id if field.to_s == "id"
|
@@ -1007,7 +1005,7 @@ module Searchkick
|
|
1007
1005
|
when :lte
|
1008
1006
|
{to: op_value, include_upper: true}
|
1009
1007
|
else
|
1010
|
-
raise "Unknown where operator: #{op.inspect}"
|
1008
|
+
raise ArgumentError, "Unknown where operator: #{op.inspect}"
|
1011
1009
|
end
|
1012
1010
|
# issue 132
|
1013
1011
|
if (existing = filters.find { |f| f[:range] && f[:range][field] })
|
@@ -1036,29 +1034,25 @@ module Searchkick
|
|
1036
1034
|
{bool: {must_not: {exists: {field: field}}}}
|
1037
1035
|
elsif value.is_a?(Regexp)
|
1038
1036
|
source = value.source
|
1039
|
-
|
1040
|
-
|
1041
|
-
Searchkick.warn("Regular expressions are always anchored in Elasticsearch")
|
1042
|
-
end
|
1037
|
+
|
1038
|
+
# TODO handle other regexp options
|
1043
1039
|
|
1044
1040
|
# TODO handle other anchor characters, like ^, $, \Z
|
1045
1041
|
if source.start_with?("\\A")
|
1046
1042
|
source = source[2..-1]
|
1047
1043
|
else
|
1048
|
-
|
1049
|
-
# source = ".*#{source}"
|
1044
|
+
source = ".*#{source}"
|
1050
1045
|
end
|
1051
1046
|
|
1052
1047
|
if source.end_with?("\\z")
|
1053
1048
|
source = source[0..-3]
|
1054
1049
|
else
|
1055
|
-
|
1056
|
-
# source = "#{source}.*"
|
1050
|
+
source = "#{source}.*"
|
1057
1051
|
end
|
1058
1052
|
|
1059
1053
|
if below710?
|
1060
1054
|
if value.casefold?
|
1061
|
-
|
1055
|
+
raise ArgumentError, "Case-insensitive flag does not work with Elasticsearch < 7.10"
|
1062
1056
|
end
|
1063
1057
|
{regexp: {field => {value: source, flags: "NONE"}}}
|
1064
1058
|
else
|
@@ -1069,9 +1063,7 @@ module Searchkick
|
|
1069
1063
|
if value.as_json.is_a?(Enumerable)
|
1070
1064
|
# query will fail, but this is better
|
1071
1065
|
# same message as Active Record
|
1072
|
-
|
1073
|
-
# raise InvalidQueryError for backward compatibility
|
1074
|
-
raise Searchkick::InvalidQueryError, "can't cast #{value.class.name}"
|
1066
|
+
raise TypeError, "can't cast #{value.class.name}"
|
1075
1067
|
end
|
1076
1068
|
|
1077
1069
|
{term: {field => {value: value}}}
|
@@ -1150,21 +1142,13 @@ module Searchkick
|
|
1150
1142
|
end
|
1151
1143
|
|
1152
1144
|
def track_total_hits?
|
1153
|
-
|
1145
|
+
searchkick_options[:deep_paging] || body_options[:track_total_hits]
|
1154
1146
|
end
|
1155
1147
|
|
1156
1148
|
def body_options
|
1157
1149
|
options[:body_options] || {}
|
1158
1150
|
end
|
1159
1151
|
|
1160
|
-
def below61?
|
1161
|
-
Searchkick.server_below?("6.1.0")
|
1162
|
-
end
|
1163
|
-
|
1164
|
-
def below70?
|
1165
|
-
Searchkick.server_below?("7.0.0")
|
1166
|
-
end
|
1167
|
-
|
1168
1152
|
def below73?
|
1169
1153
|
Searchkick.server_below?("7.3.0")
|
1170
1154
|
end
|
@@ -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
|
@@ -39,7 +40,6 @@ module Searchkick
|
|
39
40
|
_index: index.name,
|
40
41
|
_id: search_id
|
41
42
|
}
|
42
|
-
data[:_type] = document_type if Searchkick.server_below7?
|
43
43
|
data[:routing] = record.search_routing if record.respond_to?(:search_routing)
|
44
44
|
data
|
45
45
|
end
|