chewy 5.1.0 → 7.2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (234) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -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/.github/workflows/ruby.yml +73 -0
  7. data/.rubocop.yml +13 -8
  8. data/.rubocop_todo.yml +110 -22
  9. data/CHANGELOG.md +449 -347
  10. data/CODE_OF_CONDUCT.md +14 -0
  11. data/CONTRIBUTING.md +63 -0
  12. data/Gemfile +3 -7
  13. data/Guardfile +3 -1
  14. data/LICENSE.txt +1 -1
  15. data/README.md +423 -311
  16. data/chewy.gemspec +8 -10
  17. data/gemfiles/rails.5.2.activerecord.gemfile +9 -14
  18. data/gemfiles/rails.6.0.activerecord.gemfile +11 -0
  19. data/gemfiles/rails.6.1.activerecord.gemfile +13 -0
  20. data/gemfiles/rails.7.0.activerecord.gemfile +13 -0
  21. data/lib/chewy/config.rb +42 -60
  22. data/lib/chewy/errors.rb +4 -10
  23. data/lib/chewy/fields/base.rb +80 -20
  24. data/lib/chewy/fields/root.rb +7 -17
  25. data/lib/chewy/index/actions.rb +62 -35
  26. data/lib/chewy/{type → index}/adapter/active_record.rb +18 -4
  27. data/lib/chewy/{type → index}/adapter/base.rb +2 -3
  28. data/lib/chewy/{type → index}/adapter/object.rb +28 -32
  29. data/lib/chewy/{type → index}/adapter/orm.rb +26 -24
  30. data/lib/chewy/index/aliases.rb +14 -5
  31. data/lib/chewy/{type → index}/crutch.rb +5 -5
  32. data/lib/chewy/index/import/bulk_builder.rb +311 -0
  33. data/lib/chewy/{type → index}/import/bulk_request.rb +6 -7
  34. data/lib/chewy/{type → index}/import/journal_builder.rb +11 -12
  35. data/lib/chewy/{type → index}/import/routine.rb +17 -16
  36. data/lib/chewy/{type → index}/import.rb +51 -33
  37. data/lib/chewy/{type → index}/mapping.rb +32 -37
  38. data/lib/chewy/index/observe/active_record_methods.rb +87 -0
  39. data/lib/chewy/index/observe/callback.rb +34 -0
  40. data/lib/chewy/index/observe.rb +17 -0
  41. data/lib/chewy/index/specification.rb +1 -0
  42. data/lib/chewy/{type → index}/syncer.rb +61 -62
  43. data/lib/chewy/{type → index}/witchcraft.rb +15 -9
  44. data/lib/chewy/{type → index}/wrapper.rb +13 -3
  45. data/lib/chewy/index.rb +46 -96
  46. data/lib/chewy/journal.rb +25 -14
  47. data/lib/chewy/minitest/helpers.rb +86 -13
  48. data/lib/chewy/minitest/search_index_receiver.rb +22 -26
  49. data/lib/chewy/multi_search.rb +62 -0
  50. data/lib/chewy/railtie.rb +6 -20
  51. data/lib/chewy/rake_helper.rb +136 -108
  52. data/lib/chewy/rspec/build_query.rb +12 -0
  53. data/lib/chewy/rspec/helpers.rb +55 -0
  54. data/lib/chewy/rspec/update_index.rb +55 -44
  55. data/lib/chewy/rspec.rb +2 -0
  56. data/lib/chewy/runtime.rb +1 -1
  57. data/lib/chewy/search/loader.rb +19 -41
  58. data/lib/chewy/search/parameters/collapse.rb +16 -0
  59. data/lib/chewy/search/parameters/concerns/query_storage.rb +2 -2
  60. data/lib/chewy/search/parameters/ignore_unavailable.rb +27 -0
  61. data/lib/chewy/search/parameters/indices.rb +12 -57
  62. data/lib/chewy/search/parameters/none.rb +1 -3
  63. data/lib/chewy/search/parameters/order.rb +6 -19
  64. data/lib/chewy/search/parameters/source.rb +5 -1
  65. data/lib/chewy/search/parameters/track_total_hits.rb +16 -0
  66. data/lib/chewy/search/parameters.rb +7 -4
  67. data/lib/chewy/search/query_proxy.rb +9 -2
  68. data/lib/chewy/search/request.rb +180 -154
  69. data/lib/chewy/search/response.rb +5 -5
  70. data/lib/chewy/search/scoping.rb +7 -8
  71. data/lib/chewy/search/scrolling.rb +16 -13
  72. data/lib/chewy/search.rb +7 -22
  73. data/lib/chewy/stash.rb +19 -30
  74. data/lib/chewy/strategy/active_job.rb +2 -2
  75. data/lib/chewy/strategy/atomic_no_refresh.rb +18 -0
  76. data/lib/chewy/strategy/base.rb +10 -0
  77. data/lib/chewy/strategy/lazy_sidekiq.rb +64 -0
  78. data/lib/chewy/strategy/sidekiq.rb +3 -2
  79. data/lib/chewy/strategy.rb +5 -19
  80. data/lib/chewy/version.rb +1 -1
  81. data/lib/chewy.rb +36 -80
  82. data/lib/generators/chewy/install_generator.rb +1 -1
  83. data/lib/tasks/chewy.rake +26 -32
  84. data/migration_guide.md +56 -0
  85. data/spec/chewy/config_spec.rb +15 -61
  86. data/spec/chewy/fields/base_spec.rb +432 -145
  87. data/spec/chewy/fields/root_spec.rb +20 -28
  88. data/spec/chewy/fields/time_fields_spec.rb +5 -5
  89. data/spec/chewy/index/actions_spec.rb +388 -55
  90. data/spec/chewy/{type → index}/adapter/active_record_spec.rb +110 -44
  91. data/spec/chewy/{type → index}/adapter/object_spec.rb +21 -6
  92. data/spec/chewy/index/aliases_spec.rb +3 -3
  93. data/spec/chewy/index/import/bulk_builder_spec.rb +494 -0
  94. data/spec/chewy/{type → index}/import/bulk_request_spec.rb +5 -12
  95. data/spec/chewy/{type → index}/import/journal_builder_spec.rb +14 -22
  96. data/spec/chewy/{type → index}/import/routine_spec.rb +19 -19
  97. data/spec/chewy/{type → index}/import_spec.rb +149 -96
  98. data/spec/chewy/index/mapping_spec.rb +135 -0
  99. data/spec/chewy/index/observe/active_record_methods_spec.rb +68 -0
  100. data/spec/chewy/index/observe/callback_spec.rb +139 -0
  101. data/spec/chewy/index/observe_spec.rb +143 -0
  102. data/spec/chewy/index/settings_spec.rb +3 -1
  103. data/spec/chewy/index/specification_spec.rb +20 -30
  104. data/spec/chewy/{type → index}/syncer_spec.rb +14 -19
  105. data/spec/chewy/{type → index}/witchcraft_spec.rb +34 -21
  106. data/spec/chewy/index/wrapper_spec.rb +100 -0
  107. data/spec/chewy/index_spec.rb +69 -137
  108. data/spec/chewy/journal_spec.rb +46 -91
  109. data/spec/chewy/minitest/helpers_spec.rb +122 -14
  110. data/spec/chewy/minitest/search_index_receiver_spec.rb +24 -26
  111. data/spec/chewy/multi_search_spec.rb +84 -0
  112. data/spec/chewy/rake_helper_spec.rb +293 -101
  113. data/spec/chewy/rspec/build_query_spec.rb +34 -0
  114. data/spec/chewy/rspec/helpers_spec.rb +61 -0
  115. data/spec/chewy/rspec/update_index_spec.rb +106 -102
  116. data/spec/chewy/runtime_spec.rb +2 -2
  117. data/spec/chewy/search/loader_spec.rb +19 -53
  118. data/spec/chewy/search/pagination/kaminari_examples.rb +3 -5
  119. data/spec/chewy/search/pagination/kaminari_spec.rb +1 -1
  120. data/spec/chewy/search/parameters/collapse_spec.rb +5 -0
  121. data/spec/chewy/search/parameters/ignore_unavailable_spec.rb +67 -0
  122. data/spec/chewy/search/parameters/indices_spec.rb +26 -118
  123. data/spec/chewy/search/parameters/none_spec.rb +1 -1
  124. data/spec/chewy/search/parameters/order_spec.rb +18 -11
  125. data/spec/chewy/search/parameters/query_storage_examples.rb +67 -21
  126. data/spec/chewy/search/parameters/search_after_spec.rb +4 -1
  127. data/spec/chewy/search/parameters/source_spec.rb +8 -2
  128. data/spec/chewy/search/parameters/track_total_hits_spec.rb +5 -0
  129. data/spec/chewy/search/parameters_spec.rb +23 -7
  130. data/spec/chewy/search/query_proxy_spec.rb +68 -17
  131. data/spec/chewy/search/request_spec.rb +344 -149
  132. data/spec/chewy/search/response_spec.rb +35 -25
  133. data/spec/chewy/search/scrolling_spec.rb +28 -26
  134. data/spec/chewy/search_spec.rb +69 -59
  135. data/spec/chewy/stash_spec.rb +16 -26
  136. data/spec/chewy/strategy/active_job_spec.rb +23 -10
  137. data/spec/chewy/strategy/atomic_no_refresh_spec.rb +60 -0
  138. data/spec/chewy/strategy/atomic_spec.rb +9 -10
  139. data/spec/chewy/strategy/lazy_sidekiq_spec.rb +214 -0
  140. data/spec/chewy/strategy/sidekiq_spec.rb +14 -10
  141. data/spec/chewy/strategy_spec.rb +19 -15
  142. data/spec/chewy_spec.rb +17 -110
  143. data/spec/spec_helper.rb +6 -29
  144. data/spec/support/active_record.rb +43 -5
  145. metadata +102 -198
  146. data/.travis.yml +0 -45
  147. data/Appraisals +0 -81
  148. data/LEGACY_DSL.md +0 -497
  149. data/gemfiles/rails.4.0.activerecord.gemfile +0 -15
  150. data/gemfiles/rails.4.1.activerecord.gemfile +0 -15
  151. data/gemfiles/rails.4.2.activerecord.gemfile +0 -16
  152. data/gemfiles/rails.4.2.mongoid.5.2.gemfile +0 -16
  153. data/gemfiles/rails.5.0.activerecord.gemfile +0 -16
  154. data/gemfiles/rails.5.0.mongoid.6.1.gemfile +0 -16
  155. data/gemfiles/rails.5.1.activerecord.gemfile +0 -16
  156. data/gemfiles/rails.5.1.mongoid.6.3.gemfile +0 -16
  157. data/gemfiles/sequel.4.45.gemfile +0 -11
  158. data/lib/chewy/backports/deep_dup.rb +0 -46
  159. data/lib/chewy/backports/duplicable.rb +0 -91
  160. data/lib/chewy/query/compose.rb +0 -68
  161. data/lib/chewy/query/criteria.rb +0 -191
  162. data/lib/chewy/query/filters.rb +0 -244
  163. data/lib/chewy/query/loading.rb +0 -110
  164. data/lib/chewy/query/nodes/and.rb +0 -25
  165. data/lib/chewy/query/nodes/base.rb +0 -17
  166. data/lib/chewy/query/nodes/bool.rb +0 -34
  167. data/lib/chewy/query/nodes/equal.rb +0 -34
  168. data/lib/chewy/query/nodes/exists.rb +0 -20
  169. data/lib/chewy/query/nodes/expr.rb +0 -28
  170. data/lib/chewy/query/nodes/field.rb +0 -110
  171. data/lib/chewy/query/nodes/has_child.rb +0 -15
  172. data/lib/chewy/query/nodes/has_parent.rb +0 -15
  173. data/lib/chewy/query/nodes/has_relation.rb +0 -59
  174. data/lib/chewy/query/nodes/match_all.rb +0 -11
  175. data/lib/chewy/query/nodes/missing.rb +0 -20
  176. data/lib/chewy/query/nodes/not.rb +0 -25
  177. data/lib/chewy/query/nodes/or.rb +0 -25
  178. data/lib/chewy/query/nodes/prefix.rb +0 -19
  179. data/lib/chewy/query/nodes/query.rb +0 -20
  180. data/lib/chewy/query/nodes/range.rb +0 -63
  181. data/lib/chewy/query/nodes/raw.rb +0 -15
  182. data/lib/chewy/query/nodes/regexp.rb +0 -35
  183. data/lib/chewy/query/nodes/script.rb +0 -20
  184. data/lib/chewy/query/pagination.rb +0 -25
  185. data/lib/chewy/query.rb +0 -1142
  186. data/lib/chewy/search/pagination/will_paginate.rb +0 -43
  187. data/lib/chewy/search/parameters/types.rb +0 -20
  188. data/lib/chewy/strategy/resque.rb +0 -27
  189. data/lib/chewy/strategy/shoryuken.rb +0 -40
  190. data/lib/chewy/type/actions.rb +0 -43
  191. data/lib/chewy/type/adapter/mongoid.rb +0 -67
  192. data/lib/chewy/type/adapter/sequel.rb +0 -93
  193. data/lib/chewy/type/import/bulk_builder.rb +0 -122
  194. data/lib/chewy/type/observe.rb +0 -82
  195. data/lib/chewy/type.rb +0 -117
  196. data/lib/sequel/plugins/chewy_observe.rb +0 -63
  197. data/spec/chewy/query/criteria_spec.rb +0 -700
  198. data/spec/chewy/query/filters_spec.rb +0 -201
  199. data/spec/chewy/query/loading_spec.rb +0 -124
  200. data/spec/chewy/query/nodes/and_spec.rb +0 -12
  201. data/spec/chewy/query/nodes/bool_spec.rb +0 -14
  202. data/spec/chewy/query/nodes/equal_spec.rb +0 -32
  203. data/spec/chewy/query/nodes/exists_spec.rb +0 -18
  204. data/spec/chewy/query/nodes/has_child_spec.rb +0 -59
  205. data/spec/chewy/query/nodes/has_parent_spec.rb +0 -59
  206. data/spec/chewy/query/nodes/match_all_spec.rb +0 -11
  207. data/spec/chewy/query/nodes/missing_spec.rb +0 -16
  208. data/spec/chewy/query/nodes/not_spec.rb +0 -14
  209. data/spec/chewy/query/nodes/or_spec.rb +0 -12
  210. data/spec/chewy/query/nodes/prefix_spec.rb +0 -16
  211. data/spec/chewy/query/nodes/query_spec.rb +0 -12
  212. data/spec/chewy/query/nodes/range_spec.rb +0 -32
  213. data/spec/chewy/query/nodes/raw_spec.rb +0 -11
  214. data/spec/chewy/query/nodes/regexp_spec.rb +0 -43
  215. data/spec/chewy/query/nodes/script_spec.rb +0 -15
  216. data/spec/chewy/query/pagination/kaminari_spec.rb +0 -5
  217. data/spec/chewy/query/pagination/will_paginate_spec.rb +0 -5
  218. data/spec/chewy/query/pagination_spec.rb +0 -39
  219. data/spec/chewy/query_spec.rb +0 -637
  220. data/spec/chewy/search/pagination/will_paginate_examples.rb +0 -63
  221. data/spec/chewy/search/pagination/will_paginate_spec.rb +0 -23
  222. data/spec/chewy/search/parameters/types_spec.rb +0 -5
  223. data/spec/chewy/strategy/resque_spec.rb +0 -46
  224. data/spec/chewy/strategy/shoryuken_spec.rb +0 -66
  225. data/spec/chewy/type/actions_spec.rb +0 -50
  226. data/spec/chewy/type/adapter/mongoid_spec.rb +0 -372
  227. data/spec/chewy/type/adapter/sequel_spec.rb +0 -472
  228. data/spec/chewy/type/import/bulk_builder_spec.rb +0 -279
  229. data/spec/chewy/type/mapping_spec.rb +0 -173
  230. data/spec/chewy/type/observe_spec.rb +0 -137
  231. data/spec/chewy/type/wrapper_spec.rb +0 -98
  232. data/spec/chewy/type_spec.rb +0 -55
  233. data/spec/support/mongoid.rb +0 -93
  234. data/spec/support/sequel.rb +0 -80
@@ -1,43 +0,0 @@
1
- module Chewy
2
- module Search
3
- module Pagination
4
- # This module provides `WillPaginate` support for {Chewy::Search::Request}
5
- # It is included automatically if `WillPaginate` is available.
6
- #
7
- # @example
8
- # PlacesIndex.all.paginate(page: 3, per_page: 10).order(:name)
9
- # # => <PlacesIndex::Query {..., :body=>{:size=>10, :from=>20, :sort=>["name"]}}>
10
- module WillPaginate
11
- extend ActiveSupport::Concern
12
-
13
- included do
14
- include ::WillPaginate::CollectionMethods
15
- attr_reader :current_page, :per_page
16
- end
17
-
18
- def paginate(options = {})
19
- @current_page = ::WillPaginate::PageNumber(options[:page] || @current_page || 1)
20
- @page_multiplier = @current_page - 1
21
- @per_page = (options[:per_page] || @per_page || ::WillPaginate.per_page).to_i
22
-
23
- # call Chewy::Query methods to limit results
24
- limit(@per_page).offset(@page_multiplier * @per_page)
25
- end
26
-
27
- def page(page)
28
- paginate(page: page)
29
- end
30
-
31
- private
32
-
33
- def paginated_collection(collection)
34
- page = current_page || 1
35
- per = per_page || ::WillPaginate.per_page
36
- ::WillPaginate::Collection.create(page, per, total_entries) do |pager|
37
- pager.replace collection
38
- end
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,20 +0,0 @@
1
- require 'chewy/search/parameters/storage'
2
-
3
- module Chewy
4
- module Search
5
- class Parameters
6
- # A standard string array storage with one exception: rendering is empty.
7
- #
8
- # @see Chewy::Search::Parameters::StringArrayStorage
9
- class Types < Storage
10
- include StringArrayStorage
11
-
12
- # Doesn't render anything, has specialized rendering logic in
13
- # {Chewy::Search::Request}
14
- #
15
- # @return [nil]
16
- def render; end
17
- end
18
- end
19
- end
20
- end
@@ -1,27 +0,0 @@
1
- module Chewy
2
- class Strategy
3
- # The strategy works the same way as atomic, but performs
4
- # async index update driven by resque
5
- #
6
- # Chewy.strategy(:resque) do
7
- # User.all.map(&:save) # Does nothing here
8
- # Post.all.map(&:save) # And here
9
- # # It imports all the changed users and posts right here
10
- # end
11
- #
12
- class Resque < Atomic
13
- class Worker
14
- @queue = :chewy
15
-
16
- def self.perform(type, ids, options = {})
17
- options[:refresh] = !Chewy.disable_refresh_async if Chewy.disable_refresh_async
18
- type.constantize.import!(ids, options)
19
- end
20
- end
21
-
22
- def leave
23
- @stash.all? { |type, ids| ::Resque.enqueue(Chewy::Strategy::Resque::Worker, type.name, ids) }
24
- end
25
- end
26
- end
27
- end
@@ -1,40 +0,0 @@
1
- module Chewy
2
- class Strategy
3
- # The strategy works the same way as atomic, but performs
4
- # async index update driven by shoryuken
5
- #
6
- # Chewy.strategy(:shoryuken) do
7
- # User.all.map(&:save) # Does nothing here
8
- # Post.all.map(&:save) # And here
9
- # # It imports all the changed users and posts right here
10
- # end
11
- #
12
- class Shoryuken < Atomic
13
- class Worker
14
- include ::Shoryuken::Worker
15
-
16
- shoryuken_options auto_delete: true,
17
- body_parser: :json
18
-
19
- def perform(_sqs_msg, body)
20
- options = body['options'] || {}
21
- options[:refresh] = !Chewy.disable_refresh_async if Chewy.disable_refresh_async
22
- body['type'].constantize.import!(body['ids'], options.deep_symbolize_keys!)
23
- end
24
- end
25
-
26
- def leave
27
- @stash.each do |type, ids|
28
- next if ids.empty?
29
- Shoryuken::Worker.perform_async({type: type.name, ids: ids}, queue: shoryuken_queue)
30
- end
31
- end
32
-
33
- private
34
-
35
- def shoryuken_queue
36
- Chewy.settings.fetch(:shoryuken, {})[:queue] || 'chewy'
37
- end
38
- end
39
- end
40
- end
@@ -1,43 +0,0 @@
1
- module Chewy
2
- class Type
3
- module Actions
4
- extend ActiveSupport::Concern
5
-
6
- module ClassMethods
7
- # Deletes all documents of a type and reimports them
8
- #
9
- # @example
10
- # UsersIndex::User.reset
11
- #
12
- # @see Chewy::Type::Import::ClassMethods#import
13
- # @see Chewy::Type::Import::ClassMethods#import
14
- # @return [true, false] the result of import
15
- def reset
16
- delete_all
17
- import
18
- end
19
-
20
- # Performs missing and outdated objects synchronization for the current type.
21
- #
22
- # @example
23
- # UsersIndex::User.sync
24
- #
25
- # @see Chewy::Type::Syncer
26
- # @param parallel [true, Integer, Hash] options for parallel execution or the number of processes
27
- # @return [Hash{Symbol, Object}, nil] a number of missing and outdated documents reindexed and their ids, nil in case of errors
28
- def sync(parallel: nil)
29
- syncer = Syncer.new(self, parallel: parallel)
30
- count = syncer.perform
31
- {count: count, missing: syncer.missing_ids, outdated: syncer.outdated_ids} if count
32
- end
33
-
34
- # A {Chewy::Journal} instance for the particular type
35
- #
36
- # @return [Chewy::Journal] journal instance
37
- def journal
38
- @journal ||= Chewy::Journal.new(self)
39
- end
40
- end
41
- end
42
- end
43
- end
@@ -1,67 +0,0 @@
1
- require 'chewy/type/adapter/orm'
2
-
3
- module Chewy
4
- class Type
5
- module Adapter
6
- class Mongoid < Orm
7
- def self.accepts?(target)
8
- defined?(::Mongoid::Document) && (
9
- target.is_a?(Class) && target.ancestors.include?(::Mongoid::Document) ||
10
- target.is_a?(::Mongoid::Criteria))
11
- end
12
-
13
- def identify(collection)
14
- super(collection).map { |id| id.is_a?(BSON::ObjectId) ? id.to_s : id }
15
- end
16
-
17
- private
18
-
19
- def cleanup_default_scope!
20
- Chewy.logger.warn('Default type scope order, limit and offset are ignored and will be nullified') if Chewy.logger && @default_scope.options.values_at(:sort, :limit, :skip).compact.present?
21
-
22
- @default_scope.options.delete(:limit)
23
- @default_scope.options.delete(:skip)
24
- @default_scope = @default_scope.reorder(nil)
25
- end
26
-
27
- def import_scope(scope, options)
28
- pluck_in_batches(scope, options.slice(:batch_size)).map do |ids|
29
- yield grouped_objects(default_scope_where_ids_in(ids))
30
- end.all?
31
- end
32
-
33
- def primary_key
34
- :_id
35
- end
36
-
37
- def pluck(scope, fields: [])
38
- scope.pluck(primary_key, *fields)
39
- end
40
-
41
- def pluck_in_batches(scope, fields: [], batch_size: nil, **options)
42
- return enum_for(:pluck_in_batches, scope, fields: fields, batch_size: batch_size, **options) unless block_given?
43
-
44
- scope.batch_size(batch_size).no_timeout.pluck(primary_key, *fields).each_slice(batch_size) do |batch|
45
- yield batch
46
- end
47
- end
48
-
49
- def scope_where_ids_in(scope, ids)
50
- scope.where(primary_key.in => ids)
51
- end
52
-
53
- def all_scope
54
- target.all
55
- end
56
-
57
- def relation_class
58
- ::Mongoid::Criteria
59
- end
60
-
61
- def object_class
62
- ::Mongoid::Document
63
- end
64
- end
65
- end
66
- end
67
- end
@@ -1,93 +0,0 @@
1
- require 'chewy/type/adapter/base'
2
-
3
- module Chewy
4
- class Type
5
- module Adapter
6
- class Sequel < Orm
7
- attr_reader :default_scope
8
- alias_method :default_dataset, :default_scope
9
-
10
- def self.accepts?(target)
11
- defined?(::Sequel::Model) && (
12
- target.is_a?(Class) && target < ::Sequel::Model ||
13
- target.is_a?(::Sequel::Dataset))
14
- end
15
-
16
- private
17
-
18
- def cleanup_default_scope!
19
- Chewy.logger.warn('Default type scope order, limit and offset are ignored and will be nullified') if Chewy.logger && @default_scope != @default_scope.unordered.unlimited
20
-
21
- @default_scope = @default_scope.unordered.unlimited
22
- end
23
-
24
- def import_scope(scope, options)
25
- pluck_in_batches(scope, options.slice(:batch_size)).inject(true) do |result, ids|
26
- result & yield(grouped_objects(default_scope_where_ids_in(ids).all))
27
- end
28
- end
29
-
30
- def primary_key
31
- target.primary_key
32
- end
33
-
34
- def full_column_name(column)
35
- ::Sequel.qualify(target.table_name, column)
36
- end
37
-
38
- def all_scope
39
- target.dataset
40
- end
41
-
42
- def target_columns
43
- @target_columns ||= target.columns.to_set
44
- end
45
-
46
- def pluck(scope, fields: [])
47
- fields = fields.map(&:to_sym).unshift(primary_key).map do |column|
48
- target_columns.include?(column) ? full_column_name(column) : column
49
- end
50
- scope.distinct.select_map(fields.one? ? fields.first : fields)
51
- end
52
-
53
- def pluck_in_batches(scope, fields: [], batch_size: nil, **options)
54
- return enum_for(:pluck_in_batches, scope, fields: fields, batch_size: batch_size, **options) unless block_given?
55
-
56
- scope = scope.unordered.order(full_column_name(primary_key).asc).limit(batch_size)
57
-
58
- ids = pluck(scope, fields: fields)
59
- count = 0
60
-
61
- while ids.present?
62
- yield ids
63
- break if ids.size < batch_size
64
- last_id = ids.last.is_a?(Array) ? ids.last.first : ids.last
65
- ids = pluck(scope.where { |_o| full_column_name(primary_key) > last_id }, fields: fields)
66
- end
67
-
68
- count
69
- end
70
-
71
- def scope_where_ids_in(scope, ids)
72
- scope.where(full_column_name(primary_key) => Array.wrap(ids))
73
- end
74
-
75
- def model_of_relation(relation)
76
- relation.model
77
- end
78
-
79
- def relation_class
80
- ::Sequel::Dataset
81
- end
82
-
83
- def object_class
84
- ::Sequel::Model
85
- end
86
-
87
- def load_scope_objects(*args)
88
- super.all
89
- end
90
- end
91
- end
92
- end
93
- end
@@ -1,122 +0,0 @@
1
- module Chewy
2
- class Type
3
- module Import
4
- # This class purpose is to build ES client-acceptable bulk
5
- # request body from the passed objects for index and deletion.
6
- # It handles parent-child relationships as well by fetching
7
- # existing documents from ES, taking their `_parent` field and
8
- # using it in the bulk body.
9
- # If fields are passed - it creates partial update entries except for
10
- # the cases when the type has parent and parent_id has been changed.
11
- class BulkBuilder
12
- # @param type [Chewy::Type] desired type
13
- # @param index [Array<Object>] objects to index
14
- # @param delete [Array<Object>] objects or ids to delete
15
- # @param fields [Array<Symbol, String>] and array of fields for documents update
16
- def initialize(type, index: [], delete: [], fields: [])
17
- @type = type
18
- @index = index
19
- @delete = delete
20
- @fields = fields.map!(&:to_sym)
21
- end
22
-
23
- # Returns ES API-ready bulk requiest body.
24
- # @see https://github.com/elastic/elasticsearch-ruby/blob/master/elasticsearch-api/lib/elasticsearch/api/actions/bulk.rb
25
- # @return [Array<Hash>] bulk body
26
- def bulk_body
27
- @bulk_body ||= @index.flat_map(&method(:index_entry)).concat(
28
- @delete.flat_map(&method(:delete_entry))
29
- )
30
- end
31
-
32
- # The only purpose of this method is to cache document ids for
33
- # all the passed object for index to avoid ids recalculation.
34
- #
35
- # @return [Hash[String => Object]] an ids-objects index hash
36
- def index_objects_by_id
37
- @index_objects_by_id ||= index_object_ids.invert.stringify_keys!
38
- end
39
-
40
- private
41
-
42
- def crutches
43
- @crutches ||= Chewy::Type::Crutch::Crutches.new @type, @index
44
- end
45
-
46
- def parents
47
- return unless type_root.parent_id
48
-
49
- @parents ||= begin
50
- ids = @index.map do |object|
51
- object.respond_to?(:id) ? object.id : object
52
- end
53
- ids.concat(@delete.map do |object|
54
- object.respond_to?(:id) ? object.id : object
55
- end)
56
- @type.filter(ids: {values: ids}).order('_doc').pluck(:_id, :_parent).to_h
57
- end
58
- end
59
-
60
- def index_entry(object)
61
- entry = {}
62
- entry[:_id] = index_object_ids[object] if index_object_ids[object]
63
-
64
- if parents
65
- entry[:parent] = type_root.compose_parent(object)
66
- parent = entry[:_id].present? && parents[entry[:_id].to_s]
67
- end
68
-
69
- if parent && entry[:parent].to_s != parent
70
- entry[:data] = @type.compose(object, crutches)
71
- [{delete: entry.except(:data).merge(parent: parent)}, {index: entry}]
72
- elsif @fields.present?
73
- return [] unless entry[:_id]
74
- entry[:data] = {doc: @type.compose(object, crutches, fields: @fields)}
75
- [{update: entry}]
76
- else
77
- entry[:data] = @type.compose(object, crutches)
78
- [{index: entry}]
79
- end
80
- end
81
-
82
- def delete_entry(object)
83
- entry = {}
84
- entry[:_id] = entry_id(object)
85
- entry[:_id] ||= object.as_json
86
-
87
- return [] if entry[:_id].blank?
88
-
89
- if parents
90
- parent = entry[:_id].present? && parents[entry[:_id].to_s]
91
- return [] unless parent
92
- entry[:parent] = parent
93
- end
94
-
95
- [{delete: entry}]
96
- end
97
-
98
- def entry_id(object)
99
- if type_root.id
100
- type_root.compose_id(object)
101
- else
102
- id = object.id if object.respond_to?(:id)
103
- id ||= object[:id] || object['id'] if object.is_a?(Hash)
104
- id = id.to_s if defined?(BSON) && id.is_a?(BSON::ObjectId)
105
- id
106
- end
107
- end
108
-
109
- def index_object_ids
110
- @index_object_ids ||= @index.each_with_object({}) do |object, result|
111
- id = entry_id(object)
112
- result[object] = id if id.present?
113
- end
114
- end
115
-
116
- def type_root
117
- @type_root ||= @type.root
118
- end
119
- end
120
- end
121
- end
122
- end
@@ -1,82 +0,0 @@
1
- module Chewy
2
- class Type
3
- module Observe
4
- extend ActiveSupport::Concern
5
-
6
- module Helpers
7
- def update_proc(type_name, *args, &block)
8
- options = args.extract_options!
9
- method = args.first
10
-
11
- proc do
12
- reference = if type_name.is_a?(Proc)
13
- if type_name.arity.zero?
14
- instance_exec(&type_name)
15
- else
16
- type_name.call(self)
17
- end
18
- else
19
- type_name
20
- end
21
-
22
- type = Chewy.derive_type(reference)
23
-
24
- next if Chewy.strategy.current.name == :bypass
25
-
26
- backreference = if method && method.to_s == 'self'
27
- self
28
- elsif method
29
- send(method)
30
- else
31
- instance_eval(&block)
32
- end
33
-
34
- type.update_index(backreference, options)
35
- end
36
- end
37
-
38
- def extract_callback_options!(args)
39
- options = args.extract_options!
40
- result = options.each_key.with_object({}) do |key, hash|
41
- hash[key] = options.delete(key) if %i[if unless].include?(key)
42
- end
43
- args.push(options) unless options.empty?
44
- result
45
- end
46
- end
47
-
48
- extend Helpers
49
-
50
- module MongoidMethods
51
- def update_index(type_name, *args, &block)
52
- callback_options = Observe.extract_callback_options!(args)
53
- update_proc = Observe.update_proc(type_name, *args, &block)
54
-
55
- after_save(callback_options, &update_proc)
56
- after_destroy(callback_options, &update_proc)
57
- end
58
- end
59
-
60
- module ActiveRecordMethods
61
- def update_index(type_name, *args, &block)
62
- callback_options = Observe.extract_callback_options!(args)
63
- update_proc = Observe.update_proc(type_name, *args, &block)
64
-
65
- if Chewy.use_after_commit_callbacks
66
- after_commit(callback_options, &update_proc)
67
- else
68
- after_save(callback_options, &update_proc)
69
- after_destroy(callback_options, &update_proc)
70
- end
71
- end
72
- end
73
-
74
- module ClassMethods
75
- def update_index(objects, options = {})
76
- Chewy.strategy.current.update(self, objects, options)
77
- true
78
- end
79
- end
80
- end
81
- end
82
- end
data/lib/chewy/type.rb DELETED
@@ -1,117 +0,0 @@
1
- require 'chewy/search'
2
- require 'chewy/type/adapter/object'
3
- require 'chewy/type/adapter/active_record'
4
- require 'chewy/type/adapter/mongoid'
5
- require 'chewy/type/adapter/sequel'
6
- require 'chewy/type/mapping'
7
- require 'chewy/type/wrapper'
8
- require 'chewy/type/observe'
9
- require 'chewy/type/actions'
10
- require 'chewy/type/syncer'
11
- require 'chewy/type/crutch'
12
- require 'chewy/type/import'
13
- require 'chewy/type/witchcraft'
14
-
15
- module Chewy
16
- class Type
17
- IMPORT_OPTIONS_KEYS = %i[batch_size bulk_size refresh consistency replication raw_import journal pipeline].freeze
18
-
19
- include Search
20
- include Mapping
21
- include Wrapper
22
- include Observe
23
- include Actions
24
- include Crutch
25
- include Witchcraft
26
- include Import
27
-
28
- singleton_class.delegate :index_name, :derivable_index_name, :client, to: :index
29
-
30
- class_attribute :_default_import_options
31
- self._default_import_options = {}
32
-
33
- class << self
34
- # Chewy index current type belongs to. Defined inside `Chewy.create_type`
35
- #
36
- def index
37
- raise NotImplementedError, 'Looks like this type was defined outside the index scope and `.index` method is undefined for it'
38
- end
39
-
40
- # Current type adapter. Defined inside `Chewy.create_type`, derived from
41
- # `Chewy::Index.define_type` arguments.
42
- #
43
- def adapter
44
- raise NotImplementedError
45
- end
46
-
47
- # Returns type name string
48
- #
49
- def type_name
50
- adapter.type_name
51
- end
52
-
53
- # Appends type name to {Chewy::Index.derivable_name}
54
- #
55
- # @example
56
- # class Namespace::UsersIndex < Chewy::Index
57
- # define_type User
58
- # end
59
- # UsersIndex::User.derivable_name # => 'namespace/users#user'
60
- #
61
- # @see Chewy::Index.derivable_name
62
- # @return [String, nil] derivable name or nil when it is impossible to calculate
63
- def derivable_name
64
- @derivable_name ||= [index.derivable_name, type_name].join('#') if index && index.derivable_name
65
- end
66
-
67
- # This method is an API shared with {Chewy::Index}, added for convenience.
68
- #
69
- # @return [Chewy::Type] array containing itself
70
- def types
71
- [self]
72
- end
73
-
74
- # Returns list of public class methods defined in current type
75
- #
76
- def scopes
77
- public_methods - Chewy::Type.public_methods
78
- end
79
-
80
- def default_import_options(params)
81
- params.assert_valid_keys(IMPORT_OPTIONS_KEYS)
82
- self._default_import_options = _default_import_options.merge(params)
83
- end
84
-
85
- def method_missing(method, *args, &block)
86
- if index.scopes.include?(method)
87
- define_singleton_method method do |*method_args, &method_block|
88
- all.scoping { index.public_send(method, *method_args, &method_block) }
89
- end
90
- send(method, *args, &block)
91
- else
92
- super
93
- end
94
- end
95
-
96
- def respond_to_missing?(method, _)
97
- index.scopes.include?(method) || super
98
- end
99
-
100
- def const_missing(name)
101
- to_resolve = "#{self}::#{name}"
102
- to_resolve[index.to_s] = ''
103
-
104
- @__resolved_constants ||= {}
105
-
106
- if to_resolve.empty? || @__resolved_constants[to_resolve]
107
- super
108
- else
109
- @__resolved_constants[to_resolve] = true
110
- to_resolve.constantize
111
- end
112
- rescue NotImplementedError
113
- super
114
- end
115
- end
116
- end
117
- end