chewy 5.0.0 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (154) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +214 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +39 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.github/PULL_REQUEST_TEMPLATE.md +16 -0
  6. data/Appraisals +1 -17
  7. data/CHANGELOG.md +312 -356
  8. data/CODE_OF_CONDUCT.md +14 -0
  9. data/CONTRIBUTING.md +63 -0
  10. data/Gemfile +2 -0
  11. data/LICENSE.txt +1 -1
  12. data/README.md +97 -92
  13. data/chewy.gemspec +5 -5
  14. data/gemfiles/rails.5.2.activerecord.gemfile +4 -3
  15. data/gemfiles/{rails.5.0.activerecord.gemfile → rails.5.2.mongoid.6.4.gemfile} +4 -3
  16. data/gemfiles/{rails.5.0.mongoid.6.1.gemfile → rails.6.0.activerecord.gemfile} +4 -3
  17. data/gemfiles/{rails.5.1.activerecord.gemfile → rails.6.1.activerecord.gemfile} +6 -3
  18. data/lib/chewy.rb +1 -1
  19. data/lib/chewy/backports/duplicable.rb +1 -1
  20. data/lib/chewy/config.rb +2 -20
  21. data/lib/chewy/fields/base.rb +1 -7
  22. data/lib/chewy/fields/root.rb +3 -4
  23. data/lib/chewy/index.rb +6 -15
  24. data/lib/chewy/index/actions.rb +12 -4
  25. data/lib/chewy/index/aliases.rb +14 -5
  26. data/lib/chewy/multi_search.rb +62 -0
  27. data/lib/chewy/railtie.rb +3 -19
  28. data/lib/chewy/search.rb +2 -9
  29. data/lib/chewy/search/loader.rb +3 -13
  30. data/lib/chewy/search/pagination/will_paginate.rb +1 -1
  31. data/lib/chewy/search/parameters.rb +24 -6
  32. data/lib/chewy/search/parameters/allow_partial_search_results.rb +27 -0
  33. data/lib/chewy/search/parameters/indices.rb +78 -0
  34. data/lib/chewy/search/parameters/none.rb +1 -3
  35. data/lib/chewy/search/request.rb +92 -85
  36. data/lib/chewy/search/response.rb +1 -1
  37. data/lib/chewy/search/scrolling.rb +8 -7
  38. data/lib/chewy/stash.rb +3 -6
  39. data/lib/chewy/strategy/active_job.rb +1 -1
  40. data/lib/chewy/strategy/sidekiq.rb +1 -1
  41. data/lib/chewy/type.rb +4 -1
  42. data/lib/chewy/type/adapter/active_record.rb +1 -1
  43. data/lib/chewy/type/adapter/mongoid.rb +1 -1
  44. data/lib/chewy/type/adapter/orm.rb +7 -4
  45. data/lib/chewy/type/adapter/sequel.rb +1 -1
  46. data/lib/chewy/type/import.rb +14 -4
  47. data/lib/chewy/type/import/bulk_request.rb +5 -4
  48. data/lib/chewy/type/import/journal_builder.rb +2 -3
  49. data/lib/chewy/type/import/routine.rb +3 -3
  50. data/lib/chewy/type/mapping.rb +5 -5
  51. data/lib/chewy/type/observe.rb +3 -3
  52. data/lib/chewy/type/syncer.rb +2 -6
  53. data/lib/chewy/type/witchcraft.rb +4 -2
  54. data/lib/chewy/type/wrapper.rb +12 -2
  55. data/lib/chewy/version.rb +1 -1
  56. data/lib/tasks/chewy.rake +10 -10
  57. data/migration_guide.md +37 -0
  58. data/spec/chewy/config_spec.rb +1 -22
  59. data/spec/chewy/fields/base_spec.rb +15 -13
  60. data/spec/chewy/fields/root_spec.rb +4 -4
  61. data/spec/chewy/index/actions_spec.rb +120 -33
  62. data/spec/chewy/index/aliases_spec.rb +3 -3
  63. data/spec/chewy/index/specification_spec.rb +13 -13
  64. data/spec/chewy/index_spec.rb +17 -42
  65. data/spec/chewy/journal_spec.rb +25 -21
  66. data/spec/chewy/minitest/search_index_receiver_spec.rb +11 -9
  67. data/spec/chewy/multi_search_spec.rb +85 -0
  68. data/spec/chewy/rake_helper_spec.rb +102 -87
  69. data/spec/chewy/rspec/update_index_spec.rb +47 -46
  70. data/spec/chewy/runtime_spec.rb +2 -2
  71. data/spec/chewy/search/loader_spec.rb +0 -16
  72. data/spec/chewy/search/parameters/indices_spec.rb +105 -0
  73. data/spec/chewy/search/parameters/none_spec.rb +1 -1
  74. data/spec/chewy/search/parameters_spec.rb +21 -4
  75. data/spec/chewy/search/request_spec.rb +94 -78
  76. data/spec/chewy/search/response_spec.rb +27 -17
  77. data/spec/chewy/search/scrolling_spec.rb +22 -18
  78. data/spec/chewy/search_spec.rb +45 -41
  79. data/spec/chewy/stash_spec.rb +14 -12
  80. data/spec/chewy/strategy/active_job_spec.rb +15 -2
  81. data/spec/chewy/strategy/shoryuken_spec.rb +6 -2
  82. data/spec/chewy/strategy/sidekiq_spec.rb +6 -2
  83. data/spec/chewy/type/adapter/active_record_spec.rb +16 -4
  84. data/spec/chewy/type/import/bulk_builder_spec.rb +9 -94
  85. data/spec/chewy/type/import/bulk_request_spec.rb +0 -6
  86. data/spec/chewy/type/import/journal_builder_spec.rb +9 -11
  87. data/spec/chewy/type/import_spec.rb +11 -2
  88. data/spec/chewy/type/mapping_spec.rb +8 -38
  89. data/spec/chewy/type/observe_spec.rb +4 -4
  90. data/spec/chewy/type/witchcraft_spec.rb +15 -0
  91. data/spec/chewy/type/wrapper_spec.rb +3 -1
  92. data/spec/chewy_spec.rb +0 -7
  93. data/spec/spec_helper.rb +4 -8
  94. data/spec/support/active_record.rb +21 -0
  95. metadata +31 -100
  96. data/.travis.yml +0 -45
  97. data/LEGACY_DSL.md +0 -497
  98. data/gemfiles/rails.4.0.activerecord.gemfile +0 -15
  99. data/gemfiles/rails.4.1.activerecord.gemfile +0 -15
  100. data/gemfiles/rails.4.2.activerecord.gemfile +0 -16
  101. data/gemfiles/rails.4.2.mongoid.5.2.gemfile +0 -16
  102. data/gemfiles/rails.5.1.mongoid.6.3.gemfile +0 -16
  103. data/lib/chewy/query.rb +0 -1137
  104. data/lib/chewy/query/compose.rb +0 -68
  105. data/lib/chewy/query/criteria.rb +0 -191
  106. data/lib/chewy/query/filters.rb +0 -244
  107. data/lib/chewy/query/loading.rb +0 -110
  108. data/lib/chewy/query/nodes/and.rb +0 -25
  109. data/lib/chewy/query/nodes/base.rb +0 -17
  110. data/lib/chewy/query/nodes/bool.rb +0 -34
  111. data/lib/chewy/query/nodes/equal.rb +0 -34
  112. data/lib/chewy/query/nodes/exists.rb +0 -20
  113. data/lib/chewy/query/nodes/expr.rb +0 -28
  114. data/lib/chewy/query/nodes/field.rb +0 -110
  115. data/lib/chewy/query/nodes/has_child.rb +0 -15
  116. data/lib/chewy/query/nodes/has_parent.rb +0 -15
  117. data/lib/chewy/query/nodes/has_relation.rb +0 -59
  118. data/lib/chewy/query/nodes/match_all.rb +0 -11
  119. data/lib/chewy/query/nodes/missing.rb +0 -20
  120. data/lib/chewy/query/nodes/not.rb +0 -25
  121. data/lib/chewy/query/nodes/or.rb +0 -25
  122. data/lib/chewy/query/nodes/prefix.rb +0 -19
  123. data/lib/chewy/query/nodes/query.rb +0 -20
  124. data/lib/chewy/query/nodes/range.rb +0 -63
  125. data/lib/chewy/query/nodes/raw.rb +0 -15
  126. data/lib/chewy/query/nodes/regexp.rb +0 -35
  127. data/lib/chewy/query/nodes/script.rb +0 -20
  128. data/lib/chewy/query/pagination.rb +0 -25
  129. data/lib/chewy/search/parameters/types.rb +0 -20
  130. data/spec/chewy/query/criteria_spec.rb +0 -700
  131. data/spec/chewy/query/filters_spec.rb +0 -201
  132. data/spec/chewy/query/loading_spec.rb +0 -124
  133. data/spec/chewy/query/nodes/and_spec.rb +0 -12
  134. data/spec/chewy/query/nodes/bool_spec.rb +0 -14
  135. data/spec/chewy/query/nodes/equal_spec.rb +0 -32
  136. data/spec/chewy/query/nodes/exists_spec.rb +0 -18
  137. data/spec/chewy/query/nodes/has_child_spec.rb +0 -59
  138. data/spec/chewy/query/nodes/has_parent_spec.rb +0 -59
  139. data/spec/chewy/query/nodes/match_all_spec.rb +0 -11
  140. data/spec/chewy/query/nodes/missing_spec.rb +0 -16
  141. data/spec/chewy/query/nodes/not_spec.rb +0 -14
  142. data/spec/chewy/query/nodes/or_spec.rb +0 -12
  143. data/spec/chewy/query/nodes/prefix_spec.rb +0 -16
  144. data/spec/chewy/query/nodes/query_spec.rb +0 -12
  145. data/spec/chewy/query/nodes/range_spec.rb +0 -32
  146. data/spec/chewy/query/nodes/raw_spec.rb +0 -11
  147. data/spec/chewy/query/nodes/regexp_spec.rb +0 -43
  148. data/spec/chewy/query/nodes/script_spec.rb +0 -15
  149. data/spec/chewy/query/pagination/kaminari_spec.rb +0 -5
  150. data/spec/chewy/query/pagination/will_paginate_spec.rb +0 -5
  151. data/spec/chewy/query/pagination_spec.rb +0 -39
  152. data/spec/chewy/query_spec.rb +0 -637
  153. data/spec/chewy/search/parameters/indices_boost_spec.rb +0 -83
  154. data/spec/chewy/search/parameters/types_spec.rb +0 -5
@@ -23,7 +23,7 @@ module Chewy
23
23
  #
24
24
  # @return [Integer]
25
25
  def total
26
- @total ||= hits_root['total'] || 0
26
+ @total ||= hits_root.fetch('total', {}).fetch('value', 0)
27
27
  end
28
28
 
29
29
  # Response `max_score` field.
@@ -28,19 +28,22 @@ module Chewy
28
28
  return enum_for(:scroll_batches, batch_size: batch_size, scroll: scroll) unless block_given?
29
29
 
30
30
  result = perform(size: batch_size, scroll: scroll)
31
- total = [raw_limit_value, result.fetch('hits', {}).fetch('total', 0)].compact.min
31
+ total = [raw_limit_value, result.fetch('hits', {}).fetch('total', {}).fetch('value', 0)].compact.min
32
32
  last_batch_size = total % batch_size
33
33
  fetched = 0
34
+ scroll_id = nil
34
35
 
35
36
  loop do
36
37
  hits = result.fetch('hits', {}).fetch('hits', [])
37
38
  fetched += hits.size
38
39
  hits = hits.first(last_batch_size) if last_batch_size != 0 && fetched >= total
39
40
  yield(hits) if hits.present?
40
- break if fetched >= total
41
41
  scroll_id = result['_scroll_id']
42
+ break if fetched >= total
42
43
  result = perform_scroll(scroll: scroll, scroll_id: scroll_id)
43
44
  end
45
+ ensure
46
+ Chewy.client.clear_scroll(scroll_id: scroll_id) if scroll_id
44
47
  end
45
48
 
46
49
  # @!method scroll_hits(batch_size: 1000, scroll: '1m')
@@ -125,11 +128,9 @@ module Chewy
125
128
 
126
129
  def perform_scroll(body)
127
130
  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
131
+ notification_payload(request: body) do
132
+ Chewy.client.scroll(body)
133
+ end
133
134
  end
134
135
  end
135
136
  end
data/lib/chewy/stash.rb CHANGED
@@ -24,7 +24,7 @@ module Chewy
24
24
  # @param since_time [Time, DateTime] a timestamp from which we load a journal
25
25
  # @param only [Chewy::Index, Array<Chewy::Index>] journal entries related to these indices will be loaded only
26
26
  def self.entries(since_time, only: [])
27
- self.for(only).filter(range: {created_at: {gt: since_time}})
27
+ self.for(only).filter(range: {created_at: {gt: since_time}}).filter.minimum_should_match(1)
28
28
  end
29
29
 
30
30
  # Cleans up all the journal entries until the specified time. If nothing is
@@ -46,11 +46,8 @@ module Chewy
46
46
  types = something.flat_map { |s| Chewy.derive_types(s) }
47
47
  return none if something.present? && types.blank?
48
48
  scope = all
49
- types.group_by(&:index).each do |index, index_types|
50
- scope = scope.or(
51
- filter(term: {index_name: index.derivable_name})
52
- .filter(terms: {type_name: index_types.map(&:type_name)})
53
- )
49
+ types.map(&:index).uniq.each do |index|
50
+ scope = scope.or(filter(term: {index_name: index.derivable_name}))
54
51
  end
55
52
  scope
56
53
  end
@@ -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
data/lib/chewy/type.rb CHANGED
@@ -14,7 +14,10 @@ require 'chewy/type/witchcraft'
14
14
 
15
15
  module Chewy
16
16
  class Type
17
- IMPORT_OPTIONS_KEYS = %i[batch_size bulk_size refresh consistency replication raw_import journal pipeline].freeze
17
+ IMPORT_OPTIONS_KEYS = %i[
18
+ batch_size bulk_size consistency direct_import journal
19
+ pipeline raw_import refresh replication
20
+ ].freeze
18
21
 
19
22
  include Search
20
23
  include Mapping
@@ -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
@@ -45,6 +45,7 @@ module Chewy
45
45
  # Import options:
46
46
  #
47
47
  # <tt>:batch_size</tt> - import batch size, 1000 objects by default
48
+ # <tt>:direct_import</tt> - import objects without reloading
48
49
  #
49
50
  # Method handles destroyed objects as well. In case of objects ORM scope
50
51
  # or array passed, objects, responding with true to `destroyed?` method will be deleted
@@ -75,10 +76,10 @@ module Chewy
75
76
  def import(*args, &block)
76
77
  collection, options = import_args(*args)
77
78
 
78
- if collection.is_a?(relation_class)
79
- import_scope(collection, options, &block)
80
- else
79
+ if !collection.is_a?(relation_class) || options[:direct_import]
81
80
  import_objects(collection, options, &block)
81
+ else
82
+ import_scope(collection, options, &block)
82
83
  end
83
84
  end
84
85
 
@@ -89,7 +90,7 @@ module Chewy
89
90
 
90
91
  if options[:fields].present? || collection.is_a?(relation_class)
91
92
  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)
93
+ pluck_in_batches(collection, **options.slice(:fields, :batch_size, :typecast), &block)
93
94
  else
94
95
  identify(collection).each_slice(options[:batch_size]) do |batch|
95
96
  yield batch
@@ -119,6 +120,8 @@ module Chewy
119
120
  indexed = collection_ids.each_slice(options[:batch_size]).map do |ids|
120
121
  batch = if options[:raw_import]
121
122
  raw_default_scope_where_ids_in(ids, options[:raw_import])
123
+ elsif options[:direct_import]
124
+ hash.values_at(*ids.map(&:to_s))
122
125
  else
123
126
  default_scope_where_ids_in(ids)
124
127
  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
  result & yield(grouped_objects(default_scope_where_ids_in(ids).all))
27
27
  end
28
28
  end
@@ -10,7 +10,7 @@ module Chewy
10
10
 
11
11
  IMPORT_WORKER = lambda do |type, options, total, ids, index|
12
12
  ::Process.setproctitle("chewy [#{type}]: import data (#{index + 1}/#{total})")
13
- routine = Routine.new(type, options)
13
+ routine = Routine.new(type, **options)
14
14
  type.adapter.import(*ids, routine.options) do |action_objects|
15
15
  routine.process(**action_objects)
16
16
  end
@@ -19,7 +19,7 @@ module Chewy
19
19
 
20
20
  LEFTOVERS_WORKER = lambda do |type, options, total, body, index|
21
21
  ::Process.setproctitle("chewy [#{type}]: import leftovers (#{index + 1}/#{total})")
22
- routine = Routine.new(type, options)
22
+ routine = Routine.new(type, **options)
23
23
  routine.perform_bulk(body)
24
24
  routine.errors
25
25
  end
@@ -67,6 +67,7 @@ module Chewy
67
67
  # @option options [String] suffix an index name suffix, used for zero-downtime reset mostly, no suffix by default
68
68
  # @option options [Integer] bulk_size bulk API chunk size in bytes; if passed, the request is performed several times for each chunk, empty by default
69
69
  # @option options [Integer] batch_size passed to the adapter import method, used to split imported objects in chunks, 1000 by default
70
+ # @option options [Boolean] direct_import skips object reloading in ORM adapter, `false` by default
70
71
  # @option options [true, false] journal enables imported objects journaling, false by default
71
72
  # @option options [Array<Symbol, String>] update_fields list of fields for the partial import, empty by default
72
73
  # @option options [true, false] update_failover enables full objects reimport in cases of partial update errors, `true` by default
@@ -126,8 +127,9 @@ module Chewy
126
127
  private
127
128
 
128
129
  def import_routine(*args)
129
- return if args.first.blank? && !args.first.nil?
130
- routine = Routine.new(self, args.extract_options!)
130
+ return if !args.first.nil? && empty_objects_or_scope?(args.first)
131
+
132
+ routine = Routine.new(self, **args.extract_options!)
131
133
  routine.create_indexes!
132
134
 
133
135
  if routine.parallel_options
@@ -137,6 +139,14 @@ module Chewy
137
139
  end
138
140
  end
139
141
 
142
+ def empty_objects_or_scope?(objects_or_scope)
143
+ if objects_or_scope.respond_to?(:empty?)
144
+ objects_or_scope.empty?
145
+ else
146
+ objects_or_scope.blank?
147
+ end
148
+ end
149
+
140
150
  def import_linear(objects, routine)
141
151
  ActiveSupport::Notifications.instrument 'import_objects.chewy', type: self do |payload|
142
152
  adapter.import(*objects, routine.options) do |action_objects|
@@ -47,22 +47,23 @@ module Chewy
47
47
 
48
48
  def request_base
49
49
  @request_base ||= {
50
- index: @type.index_name(suffix: @suffix),
51
- type: @type.type_name
50
+ index: @type.index_name(suffix: @suffix)
52
51
  }.merge!(@bulk_options)
53
52
  end
54
53
 
55
54
  def request_bodies(body)
56
55
  if @bulk_size
56
+ serializer = ::Elasticsearch::API.serializer
57
57
  pieces = body.each_with_object(['']) do |piece, result|
58
58
  operation, meta = piece.to_a.first
59
59
  data = meta.delete(:data)
60
- piece = [{operation => meta}, data].compact.map(&:to_json).join("\n")
60
+ piece = serializer.dump(operation => meta)
61
+ piece << "\n" << serializer.dump(data) if data.present?
61
62
 
62
63
  if result.last.bytesize + piece.bytesize > @bulk_size
63
64
  result.push(piece)
64
65
  else
65
- result[-1] = [result[-1], piece].reject(&:blank?).join("\n")
66
+ result[-1].blank? ? (result[-1] = piece) : (result[-1] << "\n" << piece)
66
67
  end
67
68
  end
68
69
  pieces.each { |piece| piece << "\n" }
@@ -17,8 +17,7 @@ module Chewy
17
17
  ].compact
18
18
  ).bulk_body.each do |item|
19
19
  item.values.first.merge!(
20
- _index: Chewy::Stash::Journal.index_name,
21
- _type: Chewy::Stash::Journal::Journal.type_name
20
+ _index: Chewy::Stash::Journal.index_name
22
21
  )
23
22
  end
24
23
  end
@@ -31,7 +30,7 @@ module Chewy
31
30
  index_name: @type.index.derivable_name,
32
31
  type_name: @type.type_name,
33
32
  action: action,
34
- references: identify(objects).map(&:to_json).map(&Base64.method(:encode64)),
33
+ references: identify(objects).map { |item| Base64.encode64(::Elasticsearch::API.serializer.dump(item)) },
35
34
  created_at: Time.now.utc
36
35
  }
37
36
  end
@@ -66,11 +66,11 @@ 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
- # The main process method. Converts passed objects to thr bulk request body,
73
- # appends journal entires, performs this request and handles errors performing
72
+ # The main process method. Converts passed objects to the bulk request body,
73
+ # appends journal entries, performs this request and handles errors performing
74
74
  # failover procedures if applicable.
75
75
  #
76
76
  # @param index [Array<Object>] any acceptable objects for indexing
@@ -35,8 +35,8 @@ module Chewy
35
35
  # end
36
36
  #
37
37
  def root(**options)
38
- self.root_object ||= Chewy::Fields::Root.new(type_name, Chewy.default_root_options.merge(options))
39
- root_object.update_options!(options)
38
+ self.root_object ||= Chewy::Fields::Root.new(type_name, **Chewy.default_root_options.merge(options))
39
+ root_object.update_options!(**options)
40
40
  yield if block_given?
41
41
  root_object
42
42
  end
@@ -126,9 +126,9 @@ module Chewy
126
126
  #
127
127
  def field(*args, **options, &block)
128
128
  if args.size > 1
129
- args.map { |name| field(name, options) }
129
+ args.map { |name| field(name, **options) }
130
130
  else
131
- expand_nested(Chewy::Fields::Base.new(args.first, options), &block)
131
+ expand_nested(Chewy::Fields::Base.new(args.first, **options), &block)
132
132
  end
133
133
  end
134
134
 
@@ -183,7 +183,7 @@ module Chewy
183
183
  # Returns compiled mappings hash for current type
184
184
  #
185
185
  def mappings_hash
186
- root.mappings_hash[type_name.to_sym].present? ? root.mappings_hash : {}
186
+ root.mappings_hash
187
187
  end
188
188
 
189
189
  # Check whether the type has outdated_sync_field defined with a simple value.
@@ -63,10 +63,10 @@ module Chewy
63
63
  update_proc = Observe.update_proc(type_name, *args, &block)
64
64
 
65
65
  if Chewy.use_after_commit_callbacks
66
- after_commit(callback_options, &update_proc)
66
+ after_commit(**callback_options, &update_proc)
67
67
  else
68
- after_save(callback_options, &update_proc)
69
- after_destroy(callback_options, &update_proc)
68
+ after_save(**callback_options, &update_proc)
69
+ after_destroy(**callback_options, &update_proc)
70
70
  end
71
71
  end
72
72
  end
@@ -2,7 +2,7 @@ module Chewy
2
2
  class Type
3
3
  # This class is able to find missing and outdated documents in the ES
4
4
  # comparing ids from the data source and the ES index. Also, if `outdated_sync_field`
5
- # existss in the index definition, it performs comparison of this field
5
+ # exists in the index definition, it performs comparison of this field
6
6
  # values for each source object and corresponding ES document. Usually,
7
7
  # this field is `updated_at` and if its value in the source is not equal
8
8
  # to the value in the index - this means that this document outdated and
@@ -205,13 +205,9 @@ module Chewy
205
205
  return @outdated_sync_field_type if instance_variable_defined?(:@outdated_sync_field_type)
206
206
  return unless @type.outdated_sync_field
207
207
 
208
- mappings = @type.client.indices.get_mapping(
209
- index: @type.index_name,
210
- type: @type.type_name
211
- ).values.first.fetch('mappings', {})
208
+ mappings = @type.client.indices.get_mapping(index: @type.index_name).values.first.fetch('mappings', {})
212
209
 
213
210
  @outdated_sync_field_type = mappings
214
- .fetch(@type.type_name, {})
215
211
  .fetch('properties', {})
216
212
  .fetch(@type.outdated_sync_field.to_s, {})['type']
217
213
  rescue Elasticsearch::Transport::Transport::Errors::NotFound
@@ -58,7 +58,7 @@ module Chewy
58
58
  private
59
59
 
60
60
  def alicorn
61
- @alicorn ||= class_eval <<-RUBY, __FILE__, __LINE__ + 1
61
+ @alicorn ||= singleton_class.class_eval <<-RUBY, __FILE__, __LINE__ + 1
62
62
  -> (locals, object0, crutches) do
63
63
  #{composed_values(@type.root, 0)}
64
64
  end
@@ -79,7 +79,9 @@ module Chewy
79
79
  if field.children.present? && !field.multi_field?
80
80
  <<-RUBY
81
81
  (result#{nesting} = #{fetcher}
82
- if result#{nesting}.respond_to?(:to_ary)
82
+ if result#{nesting}.nil?
83
+ nil
84
+ elsif result#{nesting}.respond_to?(:to_ary)
83
85
  result#{nesting}.map do |object#{nesting}|
84
86
  #{composed_values(field, nesting)}
85
87
  end
@@ -41,7 +41,7 @@ module Chewy
41
41
 
42
42
  %w[_id _type _index].each do |name|
43
43
  define_method name do
44
- data[name]
44
+ _data[name]
45
45
  end
46
46
  end
47
47
 
@@ -49,6 +49,8 @@ module Chewy
49
49
  m = method.to_s
50
50
  if (name = highlight_name(m))
51
51
  highlight(name)
52
+ elsif (name = highlight_names(m))
53
+ highlights(name)
52
54
  elsif @attributes.key?(m)
53
55
  @attributes[m]
54
56
  elsif attribute_defined?(m)
@@ -60,7 +62,7 @@ module Chewy
60
62
 
61
63
  def respond_to_missing?(method, include_private = false)
62
64
  m = method.to_s
63
- highlight_name(m) || @attributes.key?(m) || attribute_defined?(m) || super
65
+ highlight_name(m) || highlight_names(m) || @attributes.key?(m) || attribute_defined?(m) || super
64
66
  end
65
67
 
66
68
  private
@@ -69,6 +71,10 @@ module Chewy
69
71
  method.sub(/_highlight\z/, '') if method.end_with?('_highlight')
70
72
  end
71
73
 
74
+ def highlight_names(method)
75
+ method.sub(/_highlights\z/, '') if method.end_with?('_highlights')
76
+ end
77
+
72
78
  def attribute_defined?(attribute)
73
79
  self.class.root && self.class.root.children.find { |a| a.name.to_s == attribute }.present?
74
80
  end
@@ -77,6 +83,10 @@ module Chewy
77
83
  _data['highlight'][attribute].first if highlight?(attribute)
78
84
  end
79
85
 
86
+ def highlights(attribute)
87
+ _data['highlight'][attribute] if highlight?(attribute)
88
+ end
89
+
80
90
  def highlight?(attribute)
81
91
  _data.key?('highlight') && _data['highlight'].key?(attribute)
82
92
  end
data/lib/chewy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Chewy
2
- VERSION = '5.0.0'.freeze
2
+ VERSION = '7.1.0'.freeze
3
3
  end
data/lib/tasks/chewy.rake CHANGED
@@ -23,22 +23,22 @@ end
23
23
  namespace :chewy do
24
24
  desc 'Destroys, recreates and imports data for the specified indexes or all of them'
25
25
  task reset: :environment do |_task, args|
26
- Chewy::RakeHelper.reset(parse_classes(args.extras))
26
+ Chewy::RakeHelper.reset(**parse_classes(args.extras))
27
27
  end
28
28
 
29
29
  desc 'Resets data for the specified indexes or all of them only if the index specification is changed'
30
30
  task upgrade: :environment do |_task, args|
31
- Chewy::RakeHelper.upgrade(parse_classes(args.extras))
31
+ Chewy::RakeHelper.upgrade(**parse_classes(args.extras))
32
32
  end
33
33
 
34
34
  desc 'Updates data for the specified indexes/types or all of them'
35
35
  task update: :environment do |_task, args|
36
- Chewy::RakeHelper.update(parse_classes(args.extras))
36
+ Chewy::RakeHelper.update(**parse_classes(args.extras))
37
37
  end
38
38
 
39
39
  desc 'Synchronizes data for the specified indexes/types or all of them'
40
40
  task sync: :environment do |_task, args|
41
- Chewy::RakeHelper.sync(parse_classes(args.extras))
41
+ Chewy::RakeHelper.sync(**parse_classes(args.extras))
42
42
  end
43
43
 
44
44
  desc 'Resets all the indexes with the specification changed and synchronizes the rest of them'
@@ -50,22 +50,22 @@ namespace :chewy do
50
50
  namespace :parallel do
51
51
  desc 'Parallel version of `rake chewy:reset`'
52
52
  task reset: :environment do |_task, args|
53
- Chewy::RakeHelper.reset(parse_parallel_args(args.extras))
53
+ Chewy::RakeHelper.reset(**parse_parallel_args(args.extras))
54
54
  end
55
55
 
56
56
  desc 'Parallel version of `rake chewy:upgrade`'
57
57
  task upgrade: :environment do |_task, args|
58
- Chewy::RakeHelper.upgrade(parse_parallel_args(args.extras))
58
+ Chewy::RakeHelper.upgrade(**parse_parallel_args(args.extras))
59
59
  end
60
60
 
61
61
  desc 'Parallel version of `rake chewy:update`'
62
62
  task update: :environment do |_task, args|
63
- Chewy::RakeHelper.update(parse_parallel_args(args.extras))
63
+ Chewy::RakeHelper.update(**parse_parallel_args(args.extras))
64
64
  end
65
65
 
66
66
  desc 'Parallel version of `rake chewy:sync`'
67
67
  task sync: :environment do |_task, args|
68
- Chewy::RakeHelper.sync(parse_parallel_args(args.extras))
68
+ Chewy::RakeHelper.sync(**parse_parallel_args(args.extras))
69
69
  end
70
70
 
71
71
  desc 'Parallel version of `rake chewy:deploy`'
@@ -79,12 +79,12 @@ namespace :chewy do
79
79
  namespace :journal do
80
80
  desc 'Applies changes that were done after the specified time for the specified indexes/types or all of them'
81
81
  task apply: :environment do |_task, args|
82
- Chewy::RakeHelper.journal_apply(parse_journal_args(args.extras))
82
+ Chewy::RakeHelper.journal_apply(**parse_journal_args(args.extras))
83
83
  end
84
84
 
85
85
  desc 'Removes journal records created before the specified timestamp for the specified indexes/types or all of them'
86
86
  task clean: :environment do |_task, args|
87
- Chewy::RakeHelper.journal_clean(parse_journal_args(args.extras))
87
+ Chewy::RakeHelper.journal_clean(**parse_journal_args(args.extras))
88
88
  end
89
89
  end
90
90