chewy 5.0.0 → 5.2.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +214 -0
  3. data/Appraisals +1 -17
  4. data/CHANGELOG.md +40 -0
  5. data/Gemfile +2 -0
  6. data/LICENSE.txt +1 -1
  7. data/README.md +61 -35
  8. data/chewy.gemspec +4 -4
  9. data/gemfiles/rails.5.2.activerecord.gemfile +4 -3
  10. data/gemfiles/{rails.5.0.activerecord.gemfile → rails.5.2.mongoid.6.4.gemfile} +4 -3
  11. data/gemfiles/{rails.5.0.mongoid.6.1.gemfile → rails.6.0.activerecord.gemfile} +4 -3
  12. data/gemfiles/{rails.5.1.activerecord.gemfile → rails.6.1.activerecord.gemfile} +6 -3
  13. data/gemfiles/ruby3.gemfile +10 -0
  14. data/lib/chewy/backports/duplicable.rb +1 -1
  15. data/lib/chewy/fields/base.rb +1 -1
  16. data/lib/chewy/fields/root.rb +2 -2
  17. data/lib/chewy/index/actions.rb +9 -3
  18. data/lib/chewy/query/loading.rb +1 -1
  19. data/lib/chewy/query/nodes/field.rb +1 -1
  20. data/lib/chewy/query.rb +5 -0
  21. data/lib/chewy/railtie.rb +1 -1
  22. data/lib/chewy/search/loader.rb +1 -1
  23. data/lib/chewy/search/parameters/allow_partial_search_results.rb +27 -0
  24. data/lib/chewy/search/parameters/indices.rb +123 -0
  25. data/lib/chewy/search/parameters.rb +24 -6
  26. data/lib/chewy/search/request.rb +76 -51
  27. data/lib/chewy/search/scrolling.rb +3 -5
  28. data/lib/chewy/search.rb +1 -5
  29. data/lib/chewy/strategy/active_job.rb +1 -1
  30. data/lib/chewy/strategy/sidekiq.rb +1 -1
  31. data/lib/chewy/type/adapter/active_record.rb +1 -1
  32. data/lib/chewy/type/adapter/mongoid.rb +1 -1
  33. data/lib/chewy/type/adapter/orm.rb +1 -1
  34. data/lib/chewy/type/adapter/sequel.rb +1 -1
  35. data/lib/chewy/type/import/bulk_request.rb +4 -2
  36. data/lib/chewy/type/import/journal_builder.rb +1 -1
  37. data/lib/chewy/type/import/routine.rb +1 -1
  38. data/lib/chewy/type/import.rb +3 -3
  39. data/lib/chewy/type/mapping.rb +4 -4
  40. data/lib/chewy/type/observe.rb +3 -3
  41. data/lib/chewy/type/witchcraft.rb +1 -1
  42. data/lib/chewy/type/wrapper.rb +1 -1
  43. data/lib/chewy/version.rb +1 -1
  44. data/lib/chewy.rb +1 -1
  45. data/spec/chewy/config_spec.rb +1 -1
  46. data/spec/chewy/fields/base_spec.rb +11 -9
  47. data/spec/chewy/index/actions_spec.rb +2 -2
  48. data/spec/chewy/journal_spec.rb +1 -1
  49. data/spec/chewy/search/parameters/indices_spec.rb +191 -0
  50. data/spec/chewy/search/parameters_spec.rb +20 -3
  51. data/spec/chewy/search/request_spec.rb +25 -9
  52. data/spec/chewy/search/response_spec.rb +8 -2
  53. data/spec/chewy/search_spec.rb +2 -2
  54. data/spec/chewy/strategy/active_job_spec.rb +15 -2
  55. data/spec/chewy/strategy/shoryuken_spec.rb +6 -2
  56. data/spec/chewy/strategy/sidekiq_spec.rb +6 -2
  57. data/spec/chewy/type/adapter/active_record_spec.rb +3 -3
  58. data/spec/chewy/type/import/bulk_builder_spec.rb +1 -1
  59. data/spec/chewy/type/observe_spec.rb +4 -4
  60. data/spec/spec_helper.rb +4 -1
  61. metadata +21 -22
  62. data/.travis.yml +0 -45
  63. data/gemfiles/rails.4.0.activerecord.gemfile +0 -15
  64. data/gemfiles/rails.4.1.activerecord.gemfile +0 -15
  65. data/gemfiles/rails.4.2.activerecord.gemfile +0 -16
  66. data/gemfiles/rails.4.2.mongoid.5.2.gemfile +0 -16
  67. data/gemfiles/rails.5.1.mongoid.6.3.gemfile +0 -16
  68. data/spec/chewy/search/parameters/indices_boost_spec.rb +0 -83
@@ -30,8 +30,8 @@ module Chewy
30
30
  # Suffixed index names might be used for zero-downtime mapping change, for example.
31
31
  # Description: (http://www.elasticsearch.org/blog/changing-mapping-with-zero-downtime/).
32
32
  #
33
- def create(*args)
34
- create!(*args)
33
+ def create(*args, **kwargs)
34
+ create!(*args, **kwargs)
35
35
  rescue Elasticsearch::Transport::Transport::Errors::BadRequest
36
36
  false
37
37
  end
@@ -74,7 +74,13 @@ module Chewy
74
74
  # UsersIndex.delete '01-2014' # deletes `users_01-2014` index
75
75
  #
76
76
  def delete(suffix = nil)
77
- result = client.indices.delete index: index_name(suffix: suffix)
77
+ # Verify that the index_name is really the index_name and not an alias.
78
+ #
79
+ # "The index parameter in the delete index API no longer accepts alias names.
80
+ # Instead, it accepts only index names (or wildcards which will expand to matching indices)."
81
+ # https://www.elastic.co/guide/en/elasticsearch/reference/6.8/breaking-changes-6.0.html#_delete_index_api_resolves_indices_expressions_only_against_indices
82
+ index_names = client.indices.get_alias(index: index_name(suffix: suffix)).keys
83
+ result = client.indices.delete index: index_names.join(',')
78
84
  Chewy.wait_for_status if result
79
85
  result
80
86
  # es-ruby >= 1.0.10 handles Elasticsearch::Transport::Transport::Errors::NotFound
@@ -94,7 +94,7 @@ module Chewy
94
94
  loaded_objects = Hash[_results.group_by(&:class).map do |type, objects|
95
95
  next if except.include?(type.type_name)
96
96
  next if only.present? && !only.include?(type.type_name)
97
- loaded = type.adapter.load(objects.map(&:id), options.merge(_type: type)) || objects
97
+ loaded = type.adapter.load(objects.map(&:id), **options.merge(_type: type)) || objects
98
98
  [type, loaded.index_by.with_index do |loaded_object, i|
99
99
  objects[i]._object = loaded_object
100
100
  objects[i]
@@ -39,7 +39,7 @@ module Chewy
39
39
  when ::Regexp
40
40
  Nodes::Regexp.new @name, other, *@args
41
41
  when ::Range
42
- Nodes::Range.new @name, *__options_merge__(gt: other.first, lt: other.last)
42
+ Nodes::Range.new @name, *__options_merge__(gt: other.begin, lt: other.end)
43
43
  else
44
44
  if other.is_a?(Array) && other.first.is_a?(::Range)
45
45
  Nodes::Range.new @name, *__options_merge__(
data/lib/chewy/query.rb CHANGED
@@ -40,6 +40,11 @@ module Chewy
40
40
  @criteria = Criteria.new
41
41
  end
42
42
 
43
+ # A compatibility layer with the new request DSL.
44
+ def render
45
+ _request
46
+ end
47
+
43
48
  # Comparation with other query or collection
44
49
  # If other is collection - search request is executed and
45
50
  # result is used for comparation
data/lib/chewy/railtie.rb CHANGED
@@ -68,7 +68,7 @@ module Chewy
68
68
  end
69
69
 
70
70
  initializer 'chewy.request_strategy' do |app|
71
- app.config.middleware.insert_after(Rails::Rack::Logger, RequestStrategy)
71
+ app.config.middleware.insert_before(ActionDispatch::ShowExceptions, RequestStrategy)
72
72
  end
73
73
 
74
74
  initializer 'chewy.add_indices_path' do |_app|
@@ -52,7 +52,7 @@ module Chewy
52
52
 
53
53
  type = derive_type(index_name, type_name)
54
54
  ids = hit_group.map { |hit| hit['_id'] }
55
- loaded = type.adapter.load(ids, @options.merge(_type: type))
55
+ loaded = type.adapter.load(ids, **@options.merge(_type: type))
56
56
  loaded ||= hit_group.map { |hit| type.build(hit) }
57
57
 
58
58
  result.merge!(hit_group.zip(loaded).to_h)
@@ -0,0 +1,27 @@
1
+ require 'chewy/search/parameters/storage'
2
+
3
+ module Chewy
4
+ module Search
5
+ class Parameters
6
+ # Stores boolean value, but has 3 states: `true`, `false` and `nil`.
7
+ #
8
+ # @see Chewy::Search::Request#allow_partial_search_results
9
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/6.4/search-request-body.html#_parameters_4
10
+ class AllowPartialSearchResults < Storage
11
+ # We don't want to render `nil`, but render `true` and `false` values.
12
+ #
13
+ # @see Chewy::Search::Parameters::Storage#render
14
+ # @return [{Symbol => Object}, nil]
15
+ def render
16
+ {self.class.param_name => value} unless value.nil?
17
+ end
18
+
19
+ private
20
+
21
+ def normalize(value)
22
+ !!value unless value.nil?
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,123 @@
1
+ require 'chewy/search/parameters/storage'
2
+
3
+ module Chewy
4
+ module Search
5
+ class Parameters
6
+ # Stores indices and/or types to query.
7
+ # Renders it to lists of string accepted by ElasticSearch
8
+ # API.
9
+ #
10
+ # The semantics behind it can be described in the
11
+ # following statements:
12
+ # 1. If index is added to the storage, no matter, a class
13
+ # or a string/symbol, it gets appended to the list.
14
+ # 2. If type is added to the storage, it filters out types
15
+ # assigned via indices.
16
+ # 3. But when a type class with non-existing index is added,
17
+ # this index got also added to the list if indices.
18
+ # 4. In cases when of an index identifier added, type
19
+ # indetifiers also got appended instead of filtering.
20
+ class Indices < Storage
21
+ # Two index storages are equal if they produce the
22
+ # same output on render.
23
+ #
24
+ # @see Chewy::Search::Parameters::Storage#==
25
+ # @param other [Chewy::Search::Parameters::Storage] any storage instance
26
+ # @return [true, false] the result of comparision
27
+ def ==(other)
28
+ super || other.class == self.class && other.render == render
29
+ end
30
+
31
+ # Just adds types to types and indices to indices.
32
+ #
33
+ # @see Chewy::Search::Parameters::Storage#update!
34
+ # @param other_value [{Symbol => Array<Chewy::Index, Chewy::Type, String, Symbol>}] any acceptable storage value
35
+ # @return [{Symbol => Array<Chewy::Index, Chewy::Type, String, Symbol>}] updated value
36
+ def update!(other_value)
37
+ new_value = normalize(other_value)
38
+
39
+ @value = {
40
+ indices: value[:indices] | new_value[:indices],
41
+ types: value[:types] | new_value[:types]
42
+ }
43
+ end
44
+
45
+ # Returns desired index and type names.
46
+ #
47
+ # @see Chewy::Search::Parameters::Storage#render
48
+ # @return [{Symbol => Array<String>}] rendered value with the parameter name
49
+ def render
50
+ {
51
+ index: index_names.uniq.sort,
52
+ type: type_names.uniq.sort
53
+ }.reject { |_, v| v.blank? }
54
+ end
55
+
56
+ # Returns index classes used for the request.
57
+ # No strings/symbos included.
58
+ #
59
+ # @return [Array<Chewy::Index>] a list of index classes
60
+ def indices
61
+ index_classes | type_classes.map(&:index)
62
+ end
63
+
64
+ # Returns type classes used for the request.
65
+ # No strings/symbos included.
66
+ #
67
+ # @return [Array<Chewy::Type>] a list of types classes
68
+ def types
69
+ type_classes | (index_classes - type_classes.map(&:index)).flat_map(&:types)
70
+ end
71
+
72
+ private
73
+
74
+ def initialize_clone(origin)
75
+ @value = origin.value.dup
76
+ end
77
+
78
+ def normalize(value)
79
+ value ||= {}
80
+
81
+ {
82
+ indices: Array.wrap(value[:indices]).flatten.compact,
83
+ types: Array.wrap(value[:types]).flatten.compact
84
+ }
85
+ end
86
+
87
+ def index_classes
88
+ value[:indices].select do |klass|
89
+ klass.is_a?(Class) && klass < Chewy::Index
90
+ end
91
+ end
92
+
93
+ def index_identifiers
94
+ value[:indices] - index_classes
95
+ end
96
+
97
+ def index_names
98
+ indices.map(&:index_name) | index_identifiers.map(&:to_s)
99
+ end
100
+
101
+ def type_classes
102
+ value[:types].select do |klass|
103
+ klass.is_a?(Class) && klass < Chewy::Type
104
+ end
105
+ end
106
+
107
+ def type_identifiers
108
+ value[:types] - type_classes
109
+ end
110
+
111
+ def type_names
112
+ type_names = types.map(&:type_name)
113
+
114
+ if index_identifiers.blank? && type_identifiers.present?
115
+ (type_names & type_identifiers.map(&:to_s)).presence || type_names
116
+ else
117
+ type_names | type_identifiers.map(&:to_s)
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -10,6 +10,8 @@ module Chewy
10
10
  # @see Chewy::Search::Request#parameters
11
11
  # @see Chewy::Search::Parameters::Storage
12
12
  class Parameters
13
+ QUERY_STRING_STORAGES = %i[indices search_type request_cache allow_partial_search_results].freeze
14
+
13
15
  # Default storage classes warehouse. It is probably possible to
14
16
  # add your own classes here if necessary, but I'm not sure it will work.
15
17
  #
@@ -33,10 +35,11 @@ module Chewy
33
35
  # limit: Chewy::Search::Parameters::Offset.new(10)
34
36
  # )
35
37
  # @param initial [{Symbol => Object, Chewy::Search::Parameters::Storage}]
36
- def initialize(initial = {})
38
+ def initialize(initial = {}, **kinitial)
37
39
  @storages = Hash.new do |hash, name|
38
40
  hash[name] = self.class.storages[name].new
39
41
  end
42
+ initial = initial.deep_dup.merge(kinitial)
40
43
  initial.each_with_object(@storages) do |(name, value), result|
41
44
  storage_class = self.class.storages[name]
42
45
  storage = value.is_a?(storage_class) ? value : storage_class.new(value)
@@ -101,11 +104,7 @@ module Chewy
101
104
  #
102
105
  # @return [Hash] request body
103
106
  def render
104
- body = @storages.except(:filter, :query, :none).values.inject({}) do |result, storage|
105
- result.merge!(storage.render || {})
106
- end
107
- body.merge!(render_query || {})
108
- body.present? ? {body: body} : {}
107
+ render_query_string_params.merge(render_body)
109
108
  end
110
109
 
111
110
  protected
@@ -126,6 +125,25 @@ module Chewy
126
125
  names
127
126
  end
128
127
 
128
+ def render_query_string_params
129
+ query_string_storages = @storages.select do |storage_name, _|
130
+ QUERY_STRING_STORAGES.include?(storage_name)
131
+ end
132
+
133
+ query_string_storages.values.inject({}) do |result, storage|
134
+ result.merge!(storage.render || {})
135
+ end
136
+ end
137
+
138
+ def render_body
139
+ exceptions = %i[filter query none] + QUERY_STRING_STORAGES
140
+ body = @storages.except(*exceptions).values.inject({}) do |result, storage|
141
+ result.merge!(storage.render || {})
142
+ end
143
+ body.merge!(render_query || {})
144
+ {body: body}
145
+ end
146
+
129
147
  def render_query
130
148
  none = @storages[:none].render
131
149
 
@@ -1,6 +1,6 @@
1
1
  module Chewy
2
2
  module Search
3
- # The main requset DSL class. Supports multiple index requests.
3
+ # The main request DSL class. Supports multiple index requests.
4
4
  # Supports ES2 and ES5 search API and query DSL.
5
5
  #
6
6
  # @note The class tries to be as immutable as possible,
@@ -26,8 +26,9 @@ module Chewy
26
26
  timeout min_score source stored_fields search_after
27
27
  load script_fields suggest aggs aggregations none
28
28
  indices_boost rescore highlight total total_count
29
- total_entries types delete_all count exists? exist? find pluck
30
- scroll_batches scroll_hits scroll_results scroll_wrappers
29
+ total_entries indices types delete_all count exists?
30
+ exist? find pluck scroll_batches scroll_hits
31
+ scroll_results scroll_wrappers
31
32
  ].to_set.freeze
32
33
  DEFAULT_BATCH_SIZE = 1000
33
34
  DEFAULT_PLUCK_BATCH_SIZE = 10_000
@@ -51,24 +52,32 @@ module Chewy
51
52
  alias_method :total_count, :total
52
53
  alias_method :total_entries, :total
53
54
 
54
- attr_reader :_indexes, :_types
55
-
56
55
  # The class is initialized with the list of chewy indexes and/or
57
56
  # types, which are later used to compose requests.
57
+ # Any symbol/string passed is treated as an index identifier.
58
58
  #
59
59
  # @example
60
+ # Chewy::Search::Request.new(:places)
61
+ # # => <Chewy::Search::Request {:index=>["places"]}>
60
62
  # Chewy::Search::Request.new(PlacesIndex)
61
63
  # # => <Chewy::Search::Request {:index=>["places"], :type=>["city", "country"]}>
62
64
  # Chewy::Search::Request.new(PlacesIndex::City)
63
65
  # # => <Chewy::Search::Request {:index=>["places"], :type=>["city"]}>
64
66
  # Chewy::Search::Request.new(UsersIndex, PlacesIndex::City)
65
67
  # # => <Chewy::Search::Request {:index=>["users", "places"], :type=>["city", "user"]}>
66
- # @param indexes_or_types [Array<Chewy::Index, Chewy::Type>] indexes and types in any combinations
67
- def initialize(*indexes_or_types)
68
- @_types = indexes_or_types.select { |klass| klass < Chewy::Type }
69
- @_indexes = indexes_or_types.select { |klass| klass < Chewy::Index }
70
- @_types |= @_indexes.flat_map(&:types)
71
- @_indexes |= @_types.map(&:index)
68
+ # @param indexes_or_types [Array<Chewy::Index, Chewy::Type, String, Symbol>] indices and types in any combinations
69
+ def initialize(*indices_or_types)
70
+ indices = indices_or_types.reject do |klass|
71
+ klass.is_a?(Class) && klass < Chewy::Type
72
+ end
73
+
74
+ types = indices_or_types.select do |klass|
75
+ klass.is_a?(Class) && klass < Chewy::Type
76
+ end
77
+
78
+ parameters.modify!(:indices) do
79
+ replace!(indices: indices, types: types)
80
+ end
72
81
  end
73
82
 
74
83
  # Underlying parameter storage collection.
@@ -110,7 +119,7 @@ module Chewy
110
119
  #
111
120
  # @return [Hash] request body
112
121
  def render
113
- @render ||= render_base.merge(parameters.render)
122
+ @render ||= parameters.render
114
123
  end
115
124
 
116
125
  # Includes the class name and the result of rendering.
@@ -281,21 +290,39 @@ module Chewy
281
290
  # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-docvalue-fields.html
282
291
  # @param values [Array<String, Symbol>] field names
283
292
  # @return [Chewy::Search::Request]
293
+ %i[order docvalue_fields].each do |name|
294
+ define_method name do |value, *values|
295
+ modify(name) { update!([value, *values]) }
296
+ end
297
+ end
298
+
299
+ # @!method indices(*values)
300
+ # Modifies `index` request parameter. Updates the storage on every call.
301
+ # Added passed indexes to the parameter list.
302
+ #
303
+ # @example
304
+ # UsersIndex.indices(CitiesIndex).indices(:another)
305
+ # # => <UsersIndex::Query {:index=>["another", "cities", "users"], :type=>["city", "user"]}>
306
+ # @see Chewy::Search::Parameters::Indices
307
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html
308
+ # @param values [Array<Chewy::Index, String, Symbol>] index names
309
+ # @return [Chewy::Search::Request]
284
310
  #
285
311
  # @!method types(*values)
286
- # Modifies `types` request parameter. Updates the storage on every call.
287
- # Constrains types passed on the request initialization.
312
+ # Modifies `type` request parameter. Updates the storage on every call.
313
+ # Constrains types passed on the request initialization or adds them
314
+ # to the list depending on circumstances.
288
315
  #
289
316
  # @example
290
- # PlacesIndex.types(:city).types(:unexistent)
291
- # # => <PlacesIndex::Query {:index=>["places"], :type=>["city"]}>
292
- # @see Chewy::Search::Parameters::Types
317
+ # UsersIndex.types(CitiesIndex::City).types(:unexistent)
318
+ # # => <UsersIndex::Query {:index=>["cities", "users"], :type=>["city", "user"]}>
319
+ # @see Chewy::Search::Parameters::Indices
293
320
  # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html
294
- # @param values [Array<String, Symbol>] type names
321
+ # @param values [Array<Chewy::Type, String, Symbol>] type names
295
322
  # @return [Chewy::Search::Request]
296
- %i[order docvalue_fields types].each do |name|
323
+ %i[indices types].each do |name|
297
324
  define_method name do |value, *values|
298
- modify(name) { update!([value, *values]) }
325
+ modify(:indices) { update!(name => [value, *values]) }
299
326
  end
300
327
  end
301
328
 
@@ -759,7 +786,7 @@ module Chewy
759
786
  # @param values [Array<String, Symbol>]
760
787
  # @return [Chewy::Search::Request] new scope
761
788
  def only(*values)
762
- chain { parameters.only!(values.flatten(1)) }
789
+ chain { parameters.only!(values.flatten(1) + [:indices]) }
763
790
  end
764
791
 
765
792
  # Returns a new scope containing all the storages except specified.
@@ -912,12 +939,11 @@ module Chewy
912
939
  def delete_all(refresh: true)
913
940
  request_body = only(WHERE_STORAGES).render.merge(refresh: refresh)
914
941
  ActiveSupport::Notifications.instrument 'delete_query.chewy',
915
- request: request_body, indexes: _indexes, types: _types,
916
- index: _indexes.one? ? _indexes.first : _indexes,
917
- type: _types.one? ? _types.first : _types do
942
+ notification_payload(request: request_body) do
918
943
  if Runtime.version < '5.0'
919
944
  delete_by_query_plugin(request_body)
920
945
  else
946
+ request_body[:body] = {query: {match_all: {}}} if request_body[:body].empty?
921
947
  Chewy.client.delete_by_query(request_body)
922
948
  end
923
949
  end
@@ -933,9 +959,7 @@ module Chewy
933
959
  private
934
960
 
935
961
  def compare_internals(other)
936
- _indexes.sort_by(&:derivable_name) == other._indexes.sort_by(&:derivable_name) &&
937
- _types.sort_by(&:derivable_name) == other._types.sort_by(&:derivable_name) &&
938
- parameters == other.parameters
962
+ parameters == other.parameters
939
963
  end
940
964
 
941
965
  def modify(name, &block)
@@ -947,45 +971,43 @@ module Chewy
947
971
  end
948
972
 
949
973
  def reset
950
- @response, @render, @render_base, @type_names, @index_names, @loader = nil
974
+ @response, @render, @loader = nil
951
975
  end
952
976
 
953
977
  def perform(additional = {})
954
978
  request_body = render.merge(additional)
955
979
  ActiveSupport::Notifications.instrument 'search_query.chewy',
956
- request: request_body, indexes: _indexes, types: _types,
957
- index: _indexes.one? ? _indexes.first : _indexes,
958
- type: _types.one? ? _types.first : _types do
959
- begin
960
- Chewy.client.search(request_body)
961
- rescue Elasticsearch::Transport::Transport::Errors::NotFound
962
- {}
980
+ notification_payload(request: request_body) do
981
+ begin
982
+ Chewy.client.search(request_body)
983
+ rescue Elasticsearch::Transport::Transport::Errors::NotFound
984
+ {}
985
+ end
963
986
  end
964
- end
965
987
  end
966
988
 
967
- def raw_limit_value
968
- parameters[:limit].value
989
+ def notification_payload(additional)
990
+ {
991
+ indexes: _indices, types: _types,
992
+ index: _indices.one? ? _indices.first : _indices,
993
+ type: _types.one? ? _types.first : _types
994
+ }.merge(additional)
969
995
  end
970
996
 
971
- def raw_offset_value
972
- parameters[:offset].value
997
+ def _indices
998
+ parameters[:indices].indices
973
999
  end
974
1000
 
975
- def index_names
976
- @index_names ||= _indexes.map(&:index_name).uniq
1001
+ def _types
1002
+ parameters[:indices].types
977
1003
  end
978
1004
 
979
- def type_names
980
- @type_names ||= if parameters[:types].value.present?
981
- _types.map(&:type_name).uniq & parameters[:types].value
982
- else
983
- _types.map(&:type_name).uniq
984
- end
1005
+ def raw_limit_value
1006
+ parameters[:limit].value
985
1007
  end
986
1008
 
987
- def render_base
988
- @render_base ||= {index: index_names, type: type_names, body: {}}
1009
+ def raw_offset_value
1010
+ parameters[:offset].value
989
1011
  end
990
1012
 
991
1013
  def delete_by_query_plugin(request)
@@ -998,7 +1020,10 @@ module Chewy
998
1020
  end
999
1021
 
1000
1022
  def loader
1001
- @loader ||= Loader.new(indexes: @_indexes, **parameters[:load].value)
1023
+ @loader ||= Loader.new(
1024
+ indexes: parameters[:indices].indices,
1025
+ **parameters[:load].value
1026
+ )
1002
1027
  end
1003
1028
 
1004
1029
  def fetch_field(hit, field)
@@ -125,11 +125,9 @@ module Chewy
125
125
 
126
126
  def perform_scroll(body)
127
127
  ActiveSupport::Notifications.instrument 'search_query.chewy',
128
- request: body, indexes: _indexes, types: _types,
129
- index: _indexes.one? ? _indexes.first : _indexes,
130
- type: _types.one? ? _types.first : _types do
131
- Chewy.client.scroll(body)
132
- end
128
+ notification_payload(request: body) do
129
+ Chewy.client.scroll(body)
130
+ end
133
131
  end
134
132
  end
135
133
  end
data/lib/chewy/search.rb CHANGED
@@ -58,11 +58,7 @@ module Chewy
58
58
  # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-uri-request.html
59
59
  # @return [Hash] the request result
60
60
  def search_string(query, options = {})
61
- options = options.merge(
62
- index: all._indexes.map(&:index_name),
63
- type: all._types.map(&:type_name),
64
- q: query
65
- )
61
+ options = options.merge(all.render.slice(:index, :type).merge(q: query))
66
62
  Chewy.client.search(options)
67
63
  end
68
64
 
@@ -11,7 +11,7 @@ module Chewy
11
11
  #
12
12
  class ActiveJob < Atomic
13
13
  class Worker < ::ActiveJob::Base
14
- queue_as :chewy
14
+ queue_as { Chewy.settings.dig(:active_job, :queue) || 'chewy' }
15
15
 
16
16
  def perform(type, ids, options = {})
17
17
  options[:refresh] = !Chewy.disable_refresh_async if Chewy.disable_refresh_async
@@ -33,7 +33,7 @@ module Chewy
33
33
  private
34
34
 
35
35
  def sidekiq_queue
36
- Chewy.settings.fetch(:sidekiq, {})[:queue] || 'chewy'
36
+ Chewy.settings.dig(:sidekiq, :queue) || 'chewy'
37
37
  end
38
38
  end
39
39
  end
@@ -22,7 +22,7 @@ module Chewy
22
22
  end
23
23
 
24
24
  def import_scope(scope, options)
25
- pluck_in_batches(scope, options.slice(:batch_size)).inject(true) do |result, ids|
25
+ pluck_in_batches(scope, **options.slice(:batch_size)).inject(true) do |result, ids|
26
26
  objects = if options[:raw_import]
27
27
  raw_default_scope_where_ids_in(ids, options[:raw_import])
28
28
  else
@@ -25,7 +25,7 @@ module Chewy
25
25
  end
26
26
 
27
27
  def import_scope(scope, options)
28
- pluck_in_batches(scope, options.slice(:batch_size)).map do |ids|
28
+ pluck_in_batches(scope, **options.slice(:batch_size)).map do |ids|
29
29
  yield grouped_objects(default_scope_where_ids_in(ids))
30
30
  end.all?
31
31
  end
@@ -89,7 +89,7 @@ module Chewy
89
89
 
90
90
  if options[:fields].present? || collection.is_a?(relation_class)
91
91
  collection = all_scope_where_ids_in(identify(collection)) unless collection.is_a?(relation_class)
92
- pluck_in_batches(collection, options.slice(:fields, :batch_size, :typecast), &block)
92
+ pluck_in_batches(collection, **options.slice(:fields, :batch_size, :typecast), &block)
93
93
  else
94
94
  identify(collection).each_slice(options[:batch_size]) do |batch|
95
95
  yield batch
@@ -22,7 +22,7 @@ module Chewy
22
22
  end
23
23
 
24
24
  def import_scope(scope, options)
25
- pluck_in_batches(scope, options.slice(:batch_size)).inject(true) do |result, ids|
25
+ pluck_in_batches(scope, **options.slice(:batch_size)).inject(true) do |result, ids|
26
26
  result & yield(grouped_objects(default_scope_where_ids_in(ids).all))
27
27
  end
28
28
  end
@@ -54,15 +54,17 @@ module Chewy
54
54
 
55
55
  def request_bodies(body)
56
56
  if @bulk_size
57
+ serializer = ::Elasticsearch::API.serializer
57
58
  pieces = body.each_with_object(['']) do |piece, result|
58
59
  operation, meta = piece.to_a.first
59
60
  data = meta.delete(:data)
60
- piece = [{operation => meta}, data].compact.map(&:to_json).join("\n")
61
+ piece = serializer.dump(operation => meta)
62
+ piece << "\n" << serializer.dump(data) if data.present?
61
63
 
62
64
  if result.last.bytesize + piece.bytesize > @bulk_size
63
65
  result.push(piece)
64
66
  else
65
- result[-1] = [result[-1], piece].reject(&:blank?).join("\n")
67
+ result[-1].blank? ? (result[-1] = piece) : (result[-1] << "\n" << piece)
66
68
  end
67
69
  end
68
70
  pieces.each { |piece| piece << "\n" }
@@ -31,7 +31,7 @@ module Chewy
31
31
  index_name: @type.index.derivable_name,
32
32
  type_name: @type.type_name,
33
33
  action: action,
34
- references: identify(objects).map(&:to_json).map(&Base64.method(:encode64)),
34
+ references: identify(objects).map { |item| Base64.encode64(::Elasticsearch::API.serializer.dump(item)) },
35
35
  created_at: Time.now.utc
36
36
  }
37
37
  end
@@ -66,7 +66,7 @@ module Chewy
66
66
  def create_indexes!
67
67
  Chewy::Stash::Journal.create if @options[:journal]
68
68
  return if Chewy.configuration[:skip_index_creation_on_import]
69
- @type.index.create!(@bulk_options.slice(:suffix)) unless @type.index.exists?
69
+ @type.index.create!(**@bulk_options.slice(:suffix)) unless @type.index.exists?
70
70
  end
71
71
 
72
72
  # The main process method. Converts passed objects to thr bulk request body,