chewy 0.10.1 → 7.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (243) hide show
  1. checksums.yaml +5 -5
  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 +74 -0
  7. data/.rubocop.yml +28 -23
  8. data/.rubocop_todo.yml +110 -22
  9. data/CHANGELOG.md +480 -298
  10. data/CODE_OF_CONDUCT.md +14 -0
  11. data/CONTRIBUTING.md +63 -0
  12. data/Gemfile +3 -5
  13. data/Guardfile +3 -1
  14. data/LICENSE.txt +1 -1
  15. data/README.md +571 -333
  16. data/chewy.gemspec +12 -15
  17. data/gemfiles/rails.5.2.activerecord.gemfile +11 -0
  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 +48 -77
  22. data/lib/chewy/errors.rb +4 -10
  23. data/lib/chewy/fields/base.rb +88 -16
  24. data/lib/chewy/fields/root.rb +15 -21
  25. data/lib/chewy/index/actions.rb +67 -38
  26. data/lib/chewy/{type → index}/adapter/active_record.rb +18 -4
  27. data/lib/chewy/{type → index}/adapter/base.rb +11 -12
  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/index/crutch.rb +40 -0
  32. data/lib/chewy/index/import/bulk_builder.rb +311 -0
  33. data/lib/chewy/{type → index}/import/bulk_request.rb +10 -9
  34. data/lib/chewy/{type → index}/import/journal_builder.rb +11 -12
  35. data/lib/chewy/{type → index}/import/routine.rb +19 -18
  36. data/lib/chewy/{type → index}/import.rb +82 -36
  37. data/lib/chewy/{type → index}/mapping.rb +63 -62
  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/settings.rb +2 -0
  42. data/lib/chewy/index/specification.rb +13 -10
  43. data/lib/chewy/{type → index}/syncer.rb +62 -63
  44. data/lib/chewy/{type → index}/witchcraft.rb +15 -9
  45. data/lib/chewy/{type → index}/wrapper.rb +16 -6
  46. data/lib/chewy/index.rb +68 -93
  47. data/lib/chewy/journal.rb +25 -14
  48. data/lib/chewy/minitest/helpers.rb +91 -18
  49. data/lib/chewy/minitest/search_index_receiver.rb +29 -33
  50. data/lib/chewy/multi_search.rb +62 -0
  51. data/lib/chewy/railtie.rb +8 -24
  52. data/lib/chewy/rake_helper.rb +141 -112
  53. data/lib/chewy/rspec/build_query.rb +12 -0
  54. data/lib/chewy/rspec/helpers.rb +55 -0
  55. data/lib/chewy/rspec/update_index.rb +58 -49
  56. data/lib/chewy/rspec.rb +2 -0
  57. data/lib/chewy/runtime.rb +1 -1
  58. data/lib/chewy/search/loader.rb +19 -41
  59. data/lib/chewy/search/parameters/allow_partial_search_results.rb +27 -0
  60. data/lib/chewy/search/parameters/collapse.rb +16 -0
  61. data/lib/chewy/search/parameters/concerns/query_storage.rb +6 -5
  62. data/lib/chewy/search/parameters/ignore_unavailable.rb +27 -0
  63. data/lib/chewy/search/parameters/indices.rb +78 -0
  64. data/lib/chewy/search/parameters/none.rb +1 -3
  65. data/lib/chewy/search/parameters/order.rb +6 -19
  66. data/lib/chewy/search/parameters/source.rb +5 -1
  67. data/lib/chewy/search/parameters/track_total_hits.rb +16 -0
  68. data/lib/chewy/search/parameters.rb +28 -8
  69. data/lib/chewy/search/query_proxy.rb +9 -2
  70. data/lib/chewy/search/request.rb +207 -157
  71. data/lib/chewy/search/response.rb +5 -5
  72. data/lib/chewy/search/scoping.rb +7 -8
  73. data/lib/chewy/search/scrolling.rb +14 -13
  74. data/lib/chewy/search.rb +7 -26
  75. data/lib/chewy/stash.rb +27 -29
  76. data/lib/chewy/strategy/active_job.rb +2 -2
  77. data/lib/chewy/strategy/atomic.rb +1 -1
  78. data/lib/chewy/strategy/atomic_no_refresh.rb +18 -0
  79. data/lib/chewy/strategy/base.rb +10 -0
  80. data/lib/chewy/strategy/delayed_sidekiq/scheduler.rb +148 -0
  81. data/lib/chewy/strategy/delayed_sidekiq/worker.rb +52 -0
  82. data/lib/chewy/strategy/delayed_sidekiq.rb +17 -0
  83. data/lib/chewy/strategy/lazy_sidekiq.rb +64 -0
  84. data/lib/chewy/strategy/sidekiq.rb +3 -2
  85. data/lib/chewy/strategy.rb +6 -19
  86. data/lib/chewy/version.rb +1 -1
  87. data/lib/chewy.rb +37 -80
  88. data/lib/generators/chewy/install_generator.rb +1 -1
  89. data/lib/tasks/chewy.rake +26 -32
  90. data/migration_guide.md +56 -0
  91. data/spec/chewy/config_spec.rb +27 -57
  92. data/spec/chewy/fields/base_spec.rb +457 -174
  93. data/spec/chewy/fields/root_spec.rb +24 -32
  94. data/spec/chewy/fields/time_fields_spec.rb +5 -5
  95. data/spec/chewy/index/actions_spec.rb +425 -60
  96. data/spec/chewy/{type → index}/adapter/active_record_spec.rb +110 -44
  97. data/spec/chewy/{type → index}/adapter/object_spec.rb +21 -6
  98. data/spec/chewy/index/aliases_spec.rb +3 -3
  99. data/spec/chewy/index/import/bulk_builder_spec.rb +494 -0
  100. data/spec/chewy/{type → index}/import/bulk_request_spec.rb +5 -12
  101. data/spec/chewy/{type → index}/import/journal_builder_spec.rb +22 -30
  102. data/spec/chewy/{type → index}/import/routine_spec.rb +19 -19
  103. data/spec/chewy/{type → index}/import_spec.rb +154 -95
  104. data/spec/chewy/index/mapping_spec.rb +135 -0
  105. data/spec/chewy/index/observe/active_record_methods_spec.rb +68 -0
  106. data/spec/chewy/index/observe/callback_spec.rb +139 -0
  107. data/spec/chewy/index/observe_spec.rb +143 -0
  108. data/spec/chewy/index/settings_spec.rb +3 -1
  109. data/spec/chewy/index/specification_spec.rb +32 -33
  110. data/spec/chewy/{type → index}/syncer_spec.rb +14 -19
  111. data/spec/chewy/{type → index}/witchcraft_spec.rb +34 -21
  112. data/spec/chewy/index/wrapper_spec.rb +100 -0
  113. data/spec/chewy/index_spec.rb +99 -114
  114. data/spec/chewy/journal_spec.rb +56 -101
  115. data/spec/chewy/minitest/helpers_spec.rb +122 -14
  116. data/spec/chewy/minitest/search_index_receiver_spec.rb +24 -26
  117. data/spec/chewy/multi_search_spec.rb +84 -0
  118. data/spec/chewy/rake_helper_spec.rb +325 -101
  119. data/spec/chewy/rspec/build_query_spec.rb +34 -0
  120. data/spec/chewy/rspec/helpers_spec.rb +61 -0
  121. data/spec/chewy/rspec/update_index_spec.rb +106 -102
  122. data/spec/chewy/runtime_spec.rb +2 -2
  123. data/spec/chewy/search/loader_spec.rb +19 -53
  124. data/spec/chewy/search/pagination/kaminari_examples.rb +3 -5
  125. data/spec/chewy/search/pagination/kaminari_spec.rb +1 -1
  126. data/spec/chewy/search/parameters/collapse_spec.rb +5 -0
  127. data/spec/chewy/search/parameters/ignore_unavailable_spec.rb +67 -0
  128. data/spec/chewy/search/parameters/indices_spec.rb +99 -0
  129. data/spec/chewy/search/parameters/none_spec.rb +1 -1
  130. data/spec/chewy/search/parameters/order_spec.rb +18 -11
  131. data/spec/chewy/search/parameters/query_storage_examples.rb +67 -21
  132. data/spec/chewy/search/parameters/search_after_spec.rb +4 -1
  133. data/spec/chewy/search/parameters/source_spec.rb +8 -2
  134. data/spec/chewy/search/parameters/track_total_hits_spec.rb +5 -0
  135. data/spec/chewy/search/parameters_spec.rb +39 -8
  136. data/spec/chewy/search/query_proxy_spec.rb +68 -17
  137. data/spec/chewy/search/request_spec.rb +360 -149
  138. data/spec/chewy/search/response_spec.rb +35 -25
  139. data/spec/chewy/search/scrolling_spec.rb +28 -26
  140. data/spec/chewy/search_spec.rb +73 -53
  141. data/spec/chewy/stash_spec.rb +16 -26
  142. data/spec/chewy/strategy/active_job_spec.rb +23 -10
  143. data/spec/chewy/strategy/atomic_no_refresh_spec.rb +60 -0
  144. data/spec/chewy/strategy/atomic_spec.rb +9 -10
  145. data/spec/chewy/strategy/delayed_sidekiq_spec.rb +190 -0
  146. data/spec/chewy/strategy/lazy_sidekiq_spec.rb +214 -0
  147. data/spec/chewy/strategy/sidekiq_spec.rb +14 -10
  148. data/spec/chewy/strategy_spec.rb +19 -15
  149. data/spec/chewy_spec.rb +17 -110
  150. data/spec/spec_helper.rb +7 -22
  151. data/spec/support/active_record.rb +43 -5
  152. metadata +123 -198
  153. data/.travis.yml +0 -53
  154. data/Appraisals +0 -79
  155. data/LEGACY_DSL.md +0 -497
  156. data/gemfiles/rails.4.0.activerecord.gemfile +0 -14
  157. data/gemfiles/rails.4.1.activerecord.gemfile +0 -14
  158. data/gemfiles/rails.4.2.activerecord.gemfile +0 -15
  159. data/gemfiles/rails.4.2.mongoid.5.1.gemfile +0 -15
  160. data/gemfiles/rails.5.0.activerecord.gemfile +0 -15
  161. data/gemfiles/rails.5.0.mongoid.6.0.gemfile +0 -15
  162. data/gemfiles/rails.5.1.activerecord.gemfile +0 -15
  163. data/gemfiles/rails.5.1.mongoid.6.1.gemfile +0 -15
  164. data/gemfiles/sequel.4.45.gemfile +0 -11
  165. data/lib/chewy/backports/deep_dup.rb +0 -46
  166. data/lib/chewy/backports/duplicable.rb +0 -91
  167. data/lib/chewy/query/compose.rb +0 -68
  168. data/lib/chewy/query/criteria.rb +0 -191
  169. data/lib/chewy/query/filters.rb +0 -227
  170. data/lib/chewy/query/loading.rb +0 -111
  171. data/lib/chewy/query/nodes/and.rb +0 -25
  172. data/lib/chewy/query/nodes/base.rb +0 -17
  173. data/lib/chewy/query/nodes/bool.rb +0 -34
  174. data/lib/chewy/query/nodes/equal.rb +0 -34
  175. data/lib/chewy/query/nodes/exists.rb +0 -20
  176. data/lib/chewy/query/nodes/expr.rb +0 -28
  177. data/lib/chewy/query/nodes/field.rb +0 -110
  178. data/lib/chewy/query/nodes/has_child.rb +0 -15
  179. data/lib/chewy/query/nodes/has_parent.rb +0 -15
  180. data/lib/chewy/query/nodes/has_relation.rb +0 -59
  181. data/lib/chewy/query/nodes/match_all.rb +0 -11
  182. data/lib/chewy/query/nodes/missing.rb +0 -20
  183. data/lib/chewy/query/nodes/not.rb +0 -25
  184. data/lib/chewy/query/nodes/or.rb +0 -25
  185. data/lib/chewy/query/nodes/prefix.rb +0 -19
  186. data/lib/chewy/query/nodes/query.rb +0 -20
  187. data/lib/chewy/query/nodes/range.rb +0 -63
  188. data/lib/chewy/query/nodes/raw.rb +0 -15
  189. data/lib/chewy/query/nodes/regexp.rb +0 -35
  190. data/lib/chewy/query/nodes/script.rb +0 -20
  191. data/lib/chewy/query/pagination.rb +0 -25
  192. data/lib/chewy/query.rb +0 -1098
  193. data/lib/chewy/search/pagination/will_paginate.rb +0 -43
  194. data/lib/chewy/search/parameters/types.rb +0 -20
  195. data/lib/chewy/strategy/resque.rb +0 -27
  196. data/lib/chewy/strategy/shoryuken.rb +0 -40
  197. data/lib/chewy/type/actions.rb +0 -43
  198. data/lib/chewy/type/adapter/mongoid.rb +0 -69
  199. data/lib/chewy/type/adapter/sequel.rb +0 -95
  200. data/lib/chewy/type/crutch.rb +0 -32
  201. data/lib/chewy/type/import/bulk_builder.rb +0 -122
  202. data/lib/chewy/type/observe.rb +0 -78
  203. data/lib/chewy/type.rb +0 -117
  204. data/lib/sequel/plugins/chewy_observe.rb +0 -78
  205. data/spec/chewy/query/criteria_spec.rb +0 -700
  206. data/spec/chewy/query/filters_spec.rb +0 -201
  207. data/spec/chewy/query/loading_spec.rb +0 -124
  208. data/spec/chewy/query/nodes/and_spec.rb +0 -12
  209. data/spec/chewy/query/nodes/bool_spec.rb +0 -14
  210. data/spec/chewy/query/nodes/equal_spec.rb +0 -32
  211. data/spec/chewy/query/nodes/exists_spec.rb +0 -18
  212. data/spec/chewy/query/nodes/has_child_spec.rb +0 -59
  213. data/spec/chewy/query/nodes/has_parent_spec.rb +0 -59
  214. data/spec/chewy/query/nodes/match_all_spec.rb +0 -11
  215. data/spec/chewy/query/nodes/missing_spec.rb +0 -16
  216. data/spec/chewy/query/nodes/not_spec.rb +0 -13
  217. data/spec/chewy/query/nodes/or_spec.rb +0 -12
  218. data/spec/chewy/query/nodes/prefix_spec.rb +0 -16
  219. data/spec/chewy/query/nodes/query_spec.rb +0 -12
  220. data/spec/chewy/query/nodes/range_spec.rb +0 -32
  221. data/spec/chewy/query/nodes/raw_spec.rb +0 -11
  222. data/spec/chewy/query/nodes/regexp_spec.rb +0 -43
  223. data/spec/chewy/query/nodes/script_spec.rb +0 -15
  224. data/spec/chewy/query/pagination/kaminari_spec.rb +0 -5
  225. data/spec/chewy/query/pagination/will_paginate_spec.rb +0 -5
  226. data/spec/chewy/query/pagination_spec.rb +0 -39
  227. data/spec/chewy/query_spec.rb +0 -636
  228. data/spec/chewy/search/pagination/will_paginate_examples.rb +0 -63
  229. data/spec/chewy/search/pagination/will_paginate_spec.rb +0 -23
  230. data/spec/chewy/search/parameters/indices_boost_spec.rb +0 -83
  231. data/spec/chewy/search/parameters/types_spec.rb +0 -5
  232. data/spec/chewy/strategy/resque_spec.rb +0 -46
  233. data/spec/chewy/strategy/shoryuken_spec.rb +0 -64
  234. data/spec/chewy/type/actions_spec.rb +0 -50
  235. data/spec/chewy/type/adapter/mongoid_spec.rb +0 -372
  236. data/spec/chewy/type/adapter/sequel_spec.rb +0 -472
  237. data/spec/chewy/type/import/bulk_builder_spec.rb +0 -279
  238. data/spec/chewy/type/mapping_spec.rb +0 -142
  239. data/spec/chewy/type/observe_spec.rb +0 -137
  240. data/spec/chewy/type/wrapper_spec.rb +0 -98
  241. data/spec/chewy/type_spec.rb +0 -55
  242. data/spec/support/mongoid.rb +0 -93
  243. data/spec/support/sequel.rb +0 -80
@@ -1,24 +1,22 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  # TODO: add more specs here later
4
- describe Chewy::Type::Import::Routine do
4
+ describe Chewy::Index::Import::Routine do
5
5
  before { Chewy.massacre }
6
6
  before do
7
7
  stub_index(:cities) do
8
- define_type :city do
9
- field :name
10
- field :object, type: 'object'
11
- end
8
+ field :name
9
+ field :object, type: 'object'
12
10
  end
13
11
  CitiesIndex.create!
14
12
  end
15
13
 
16
- let(:index) { [double(id: 1, name: 'Name', object: {}), double(id: 2, name: 'Name', object: {})] }
17
- let(:delete) { [double(id: 3, name: 'Name')] }
14
+ let(:index) { [double('city_1', id: 1, name: 'Name', object: {}), double('city_2', id: 2, name: 'Name', object: {})] }
15
+ let(:delete) { [double('city_3', id: 3, name: 'Name', object: {})] }
18
16
 
19
17
  describe '#options' do
20
18
  specify do
21
- expect(described_class.new(CitiesIndex::City).options).to eq(
19
+ expect(described_class.new(CitiesIndex).options).to eq(
22
20
  journal: nil,
23
21
  refresh: true,
24
22
  update_failover: true,
@@ -29,7 +27,7 @@ describe Chewy::Type::Import::Routine do
29
27
 
30
28
  specify do
31
29
  expect(described_class.new(
32
- CitiesIndex::City, batch_size: 100, bulk_size: 1.megabyte, refresh: false
30
+ CitiesIndex, batch_size: 100, bulk_size: 1.megabyte, refresh: false
33
31
  ).options).to eq(
34
32
  journal: nil,
35
33
  refresh: false,
@@ -43,7 +41,7 @@ describe Chewy::Type::Import::Routine do
43
41
  context do
44
42
  before { allow(Chewy).to receive_messages(configuration: Chewy.configuration.merge(journal: true)) }
45
43
  specify do
46
- expect(described_class.new(CitiesIndex::City).options).to eq(
44
+ expect(described_class.new(CitiesIndex).options).to eq(
47
45
  journal: true,
48
46
  refresh: true,
49
47
  update_failover: true,
@@ -55,24 +53,26 @@ describe Chewy::Type::Import::Routine do
55
53
 
56
54
  specify do
57
55
  expect(CitiesIndex.client).to receive(:bulk).with(hash_including(refresh: true))
58
- described_class.new(CitiesIndex::City).process(index: index)
56
+ described_class.new(CitiesIndex).process(index: index)
59
57
  end
60
58
 
61
59
  specify do
62
60
  expect(CitiesIndex.client).to receive(:bulk).with(hash_including(refresh: false))
63
- described_class.new(CitiesIndex::City, refresh: false).process(index: index)
61
+ described_class.new(CitiesIndex, refresh: false).process(index: index)
64
62
  end
65
63
  end
66
64
 
67
65
  describe '#parallel_options' do
68
- specify { expect(described_class.new(CitiesIndex::City).parallel_options).to be_nil }
69
- specify { expect(described_class.new(CitiesIndex::City, parallel: true).parallel_options).to eq({}) }
70
- specify { expect(described_class.new(CitiesIndex::City, parallel: 3).parallel_options).to eq(in_processes: 3) }
71
- specify { expect(described_class.new(CitiesIndex::City, parallel: {in_threads: 2}).parallel_options).to eq(in_threads: 2) }
66
+ specify { expect(described_class.new(CitiesIndex).parallel_options).to be_nil }
67
+ specify { expect(described_class.new(CitiesIndex, parallel: true).parallel_options).to eq({}) }
68
+ specify { expect(described_class.new(CitiesIndex, parallel: 3).parallel_options).to eq(in_processes: 3) }
69
+ specify do
70
+ expect(described_class.new(CitiesIndex, parallel: {in_threads: 2}).parallel_options).to eq(in_threads: 2)
71
+ end
72
72
  end
73
73
 
74
74
  describe '#stats' do
75
- subject { described_class.new(CitiesIndex::City) }
75
+ subject { described_class.new(CitiesIndex) }
76
76
 
77
77
  specify { expect(subject.stats).to eq({}) }
78
78
  specify do
@@ -92,8 +92,8 @@ describe Chewy::Type::Import::Routine do
92
92
  end
93
93
 
94
94
  describe '#errors' do
95
- subject { described_class.new(CitiesIndex::City) }
96
- let(:index) { [double(id: 1, name: 'Name', object: ''), double(id: 2, name: 'Name', object: {})] }
95
+ subject { described_class.new(CitiesIndex) }
96
+ let(:index) { [double('city_1', id: 1, name: 'Name', object: ''), double('city_2', id: 2, name: 'Name', object: {})] }
97
97
 
98
98
  specify { expect(subject.errors).to eq([]) }
99
99
  specify do
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Chewy::Type::Import do
3
+ describe Chewy::Index::Import do
4
4
  before { Chewy.massacre }
5
5
 
6
6
  before do
@@ -9,14 +9,13 @@ describe Chewy::Type::Import do
9
9
 
10
10
  before do
11
11
  stub_index(:cities) do
12
- define_type City do
13
- field :name
14
- end
12
+ index_scope City
13
+ field :name
15
14
  end
16
15
  end
17
16
 
18
17
  def imported_cities
19
- CitiesIndex::City.all.map do |city|
18
+ CitiesIndex.all.map do |city|
20
19
  city.attributes.except('_score', '_explanation')
21
20
  end
22
21
  end
@@ -37,7 +36,13 @@ describe Chewy::Type::Import do
37
36
  specify 'lazy (default)' do
38
37
  expect(CitiesIndex).to receive(:exists?).and_call_original
39
38
  expect(CitiesIndex).to receive(:create!).and_call_original
40
- CitiesIndex::City.import(dummy_city)
39
+ CitiesIndex.import(dummy_city)
40
+ end
41
+
42
+ specify 'lazy without objects' do
43
+ expect(CitiesIndex).not_to receive(:exists?)
44
+ expect(CitiesIndex).not_to receive(:create!)
45
+ CitiesIndex.import([])
41
46
  end
42
47
 
43
48
  context 'skip' do
@@ -52,7 +57,7 @@ describe Chewy::Type::Import do
52
57
  specify do
53
58
  expect(CitiesIndex).not_to receive(:exists?)
54
59
  expect(CitiesIndex).not_to receive(:create!)
55
- CitiesIndex::City.import(dummy_city)
60
+ CitiesIndex.import(dummy_city)
56
61
  end
57
62
  end
58
63
  end
@@ -63,35 +68,36 @@ describe Chewy::Type::Import do
63
68
  specify { expect(import(dummy_cities)).to eq(true) }
64
69
  specify { expect(import(dummy_cities.map(&:id))).to eq(true) }
65
70
 
66
- specify { expect { import([]) }.not_to update_index(CitiesIndex::City) }
67
- specify { expect { import }.to update_index(CitiesIndex::City).and_reindex(dummy_cities) }
68
- specify { expect { import dummy_cities }.to update_index(CitiesIndex::City).and_reindex(dummy_cities) }
69
- specify { expect { import dummy_cities.map(&:id) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities) }
71
+ specify { expect { import([]) }.not_to update_index(CitiesIndex) }
72
+ specify { expect { import }.to update_index(CitiesIndex).and_reindex(dummy_cities) }
73
+ specify { expect { import dummy_cities }.to update_index(CitiesIndex).and_reindex(dummy_cities) }
74
+ specify { expect { import dummy_cities.map(&:id) }.to update_index(CitiesIndex).and_reindex(dummy_cities) }
70
75
 
71
76
  describe 'criteria-driven importing' do
72
77
  let(:names) { %w[name0 name1] }
73
78
 
74
- context 'mongoid', :mongoid do
75
- specify { expect { import(City.where(:name.in => names)) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities.first(2)) }
76
- specify { expect { import(City.where(:name.in => names).map(&:id)) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities.first(2)) }
77
- end
78
-
79
79
  context 'active record', :active_record do
80
- specify { expect { import(City.where(name: names)) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities.first(2)) }
81
- specify { expect { import(City.where(name: names).map(&:id)) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities.first(2)) }
80
+ specify do
81
+ expect { import(City.where(name: names)) }
82
+ .to update_index(CitiesIndex).and_reindex(dummy_cities.first(2))
83
+ end
84
+ specify do
85
+ expect { import(City.where(name: names).map(&:id)) }
86
+ .to update_index(CitiesIndex).and_reindex(dummy_cities.first(2))
87
+ end
82
88
  end
83
89
  end
84
90
 
85
91
  specify do
86
92
  dummy_cities.first.destroy
87
93
  expect { import dummy_cities }
88
- .to update_index(CitiesIndex::City).and_reindex(dummy_cities.from(1)).and_delete(dummy_cities.first)
94
+ .to update_index(CitiesIndex).and_reindex(dummy_cities.from(1)).and_delete(dummy_cities.first)
89
95
  end
90
96
 
91
97
  specify do
92
98
  dummy_cities.first.destroy
93
99
  expect { import dummy_cities.map(&:id) }
94
- .to update_index(CitiesIndex::City).and_reindex(dummy_cities.from(1)).and_delete(dummy_cities.first)
100
+ .to update_index(CitiesIndex).and_reindex(dummy_cities.from(1)).and_delete(dummy_cities.first)
95
101
  end
96
102
 
97
103
  specify do
@@ -114,7 +120,10 @@ describe Chewy::Type::Import do
114
120
  context ':bulk_size' do
115
121
  let!(:dummy_cities) { Array.new(3) { |i| City.create(id: i + 1, name: "name#{i}" * 20) } }
116
122
 
117
- specify { expect { import(dummy_cities, bulk_size: 1.2.kilobyte) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities) }
123
+ specify do
124
+ expect { import(dummy_cities, bulk_size: 1.2.kilobyte) }
125
+ .to update_index(CitiesIndex).and_reindex(dummy_cities)
126
+ end
118
127
 
119
128
  context do
120
129
  before { expect(Chewy.client).to receive(:bulk).exactly(3).times.and_call_original }
@@ -126,31 +135,29 @@ describe Chewy::Type::Import do
126
135
  before do
127
136
  names = %w[name0 name1]
128
137
 
129
- criteria = case adapter
130
- when :mongoid
131
- {:name.in => names}
132
- else
133
- {name: names}
134
- end
138
+ criteria = {name: names}
135
139
 
136
140
  stub_index(:cities) do
137
- define_type City.where(criteria) do
138
- field :name
139
- end
141
+ index_scope City.where(criteria)
142
+ field :name
140
143
  end
141
144
  end
142
145
 
143
- specify { expect { import }.to update_index(CitiesIndex::City).and_reindex(dummy_cities.first(2)) }
146
+ specify { expect { import }.to update_index(CitiesIndex).and_reindex(dummy_cities.first(2)) }
144
147
 
145
- context 'mongoid', :mongoid do
148
+ context 'active record', :active_record do
146
149
  specify do
147
- expect { import City.where(_id: dummy_cities.first.id) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities.first).only
150
+ expect { import City.where(id: dummy_cities.first.id) }
151
+ .to update_index(CitiesIndex).and_reindex(dummy_cities.first).only
148
152
  end
149
- end
150
153
 
151
- context 'active record', :active_record do
152
154
  specify do
153
- expect { import City.where(id: dummy_cities.first.id) }.to update_index(CitiesIndex::City).and_reindex(dummy_cities.first).only
155
+ allow(CitiesIndex).to receive(:import_linear).and_return(double(present?: false))
156
+ allow(CitiesIndex).to receive(:import_parallel).and_return(double(present?: false))
157
+
158
+ expects_no_query(except: /SELECT\s+1\s+AS\s+one\s+FROM/) do
159
+ import City.where(id: dummy_cities.first.id)
160
+ end
154
161
  end
155
162
  end
156
163
  end
@@ -160,28 +167,27 @@ describe Chewy::Type::Import do
160
167
  payload = subscribe_notification
161
168
  dummy_cities.first.destroy
162
169
  import dummy_cities
163
- expect(payload).to eq(type: CitiesIndex::City, import: {delete: 1, index: 2})
170
+ expect(payload).to eq(index: CitiesIndex, import: {delete: 1, index: 2})
164
171
  end
165
172
 
166
173
  specify do
167
174
  payload = subscribe_notification
168
175
  dummy_cities.first.destroy
169
176
  import dummy_cities, batch_size: 2
170
- expect(payload).to eq(type: CitiesIndex::City, import: {delete: 1, index: 2})
177
+ expect(payload).to eq(index: CitiesIndex, import: {delete: 1, index: 2})
171
178
  end
172
179
 
173
180
  specify do
174
181
  payload = subscribe_notification
175
182
  import dummy_cities, batch_size: 2
176
- expect(payload).to eq(type: CitiesIndex::City, import: {index: 3})
183
+ expect(payload).to eq(index: CitiesIndex, import: {index: 3})
177
184
  end
178
185
 
179
186
  context do
180
187
  before do
181
188
  stub_index(:cities) do
182
- define_type City do
183
- field :name, type: 'object'
184
- end
189
+ index_scope City
190
+ field :name, type: 'object'
185
191
  end
186
192
  end
187
193
 
@@ -195,7 +201,7 @@ describe Chewy::Type::Import do
195
201
  specify do
196
202
  payload = subscribe_notification
197
203
  import dummy_cities, batch_size: 2
198
- expect(payload).to eq(type: CitiesIndex::City,
204
+ expect(payload).to eq(index: CitiesIndex,
199
205
  errors: {index: {mapper_parsing_exception => %w[1 2 3]}},
200
206
  import: {index: 3})
201
207
  end
@@ -203,7 +209,7 @@ describe Chewy::Type::Import do
203
209
  end
204
210
 
205
211
  context 'fields' do
206
- before { CitiesIndex::City.import!(dummy_cities.first(2)) }
212
+ before { CitiesIndex.import!(dummy_cities.first(2)) }
207
213
 
208
214
  context do
209
215
  before { expect(Chewy.client).to receive(:bulk).twice.and_call_original }
@@ -211,7 +217,7 @@ describe Chewy::Type::Import do
211
217
  end
212
218
 
213
219
  context do
214
- before { CitiesIndex::City.import!(dummy_cities.last) }
220
+ before { CitiesIndex.import!(dummy_cities.last) }
215
221
  before { expect(Chewy.client).to receive(:bulk).once.and_call_original }
216
222
  specify { expect(import(dummy_cities, update_fields: [:name])).to eq(true) }
217
223
  end
@@ -220,10 +226,8 @@ describe Chewy::Type::Import do
220
226
  context 'fields integrational' do
221
227
  before do
222
228
  stub_index(:cities) do
223
- define_type :city do
224
- field :name
225
- field :object, type: 'object'
226
- end
229
+ field :name
230
+ field :object, type: 'object'
227
231
  end
228
232
  end
229
233
 
@@ -251,9 +255,14 @@ describe Chewy::Type::Import do
251
255
  import(objects, update_fields: %i[name])
252
256
 
253
257
  expect(payload).to eq(
254
- errors: {index: {{'type' => 'mapper_parsing_exception', 'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'} => %w[2 4]}},
258
+ errors: {
259
+ index: {{
260
+ 'type' => 'mapper_parsing_exception',
261
+ 'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'
262
+ } => %w[2 4]}
263
+ },
255
264
  import: {index: 6},
256
- type: CitiesIndex::City
265
+ index: CitiesIndex
257
266
  )
258
267
  expect(imported_cities).to match_array([
259
268
  {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}},
@@ -269,9 +278,14 @@ describe Chewy::Type::Import do
269
278
  import(objects, batch_size: 2, update_fields: %i[name])
270
279
 
271
280
  expect(payload).to eq(
272
- errors: {index: {{'type' => 'mapper_parsing_exception', 'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'} => %w[2 4]}},
281
+ errors: {
282
+ index: {{
283
+ 'type' => 'mapper_parsing_exception',
284
+ 'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'
285
+ } => %w[2 4]}
286
+ },
273
287
  import: {index: 6},
274
- type: CitiesIndex::City
288
+ index: CitiesIndex
275
289
  )
276
290
  expect(imported_cities).to match_array([
277
291
  {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}},
@@ -281,7 +295,7 @@ describe Chewy::Type::Import do
281
295
  end
282
296
 
283
297
  context do
284
- before { CitiesIndex::City.import!(objects[4]) }
298
+ before { CitiesIndex.import!(objects[4]) }
285
299
 
286
300
  specify do
287
301
  payload = subscribe_notification
@@ -290,9 +304,14 @@ describe Chewy::Type::Import do
290
304
  import(objects, batch_size: 2, update_fields: %i[name])
291
305
 
292
306
  expect(payload).to eq(
293
- errors: {index: {{'type' => 'mapper_parsing_exception', 'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'} => %w[2 4]}},
307
+ errors: {
308
+ index: {{
309
+ 'type' => 'mapper_parsing_exception',
310
+ 'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'
311
+ } => %w[2 4]}
312
+ },
294
313
  import: {index: 6},
295
- type: CitiesIndex::City
314
+ index: CitiesIndex
296
315
  )
297
316
  expect(imported_cities).to match_array([
298
317
  {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}},
@@ -303,7 +322,7 @@ describe Chewy::Type::Import do
303
322
  end
304
323
 
305
324
  context do
306
- before { CitiesIndex::City.import!(old_objects[1], old_objects[3], objects[4]) }
325
+ before { CitiesIndex.import!(old_objects[1], old_objects[3], objects[4]) }
307
326
 
308
327
  specify do
309
328
  payload = subscribe_notification
@@ -313,7 +332,7 @@ describe Chewy::Type::Import do
313
332
 
314
333
  expect(payload).to eq(
315
334
  import: {index: 6},
316
- type: CitiesIndex::City
335
+ index: CitiesIndex
317
336
  )
318
337
  expect(imported_cities).to match_array([
319
338
  {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}},
@@ -332,7 +351,7 @@ describe Chewy::Type::Import do
332
351
 
333
352
  expect(payload).to eq(
334
353
  import: {index: 6},
335
- type: CitiesIndex::City
354
+ index: CitiesIndex
336
355
  )
337
356
  expect(imported_cities).to match_array([
338
357
  {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 11}},
@@ -351,8 +370,8 @@ describe Chewy::Type::Import do
351
370
 
352
371
  # Full match doesn't work here.
353
372
  expect(payload[:errors][:update].keys).to match([
354
- hash_including('type' => 'document_missing_exception', 'reason' => '[city][1]: document missing'),
355
- hash_including('type' => 'document_missing_exception', 'reason' => '[city][3]: document missing')
373
+ hash_including('type' => 'document_missing_exception', 'reason' => '[_doc][1]: document missing'),
374
+ hash_including('type' => 'document_missing_exception', 'reason' => '[_doc][3]: document missing')
356
375
  ])
357
376
  expect(payload[:errors][:update].values).to eq([['1'], ['3']])
358
377
  expect(imported_cities).to match_array([
@@ -364,7 +383,7 @@ describe Chewy::Type::Import do
364
383
  end
365
384
 
366
385
  context do
367
- before { CitiesIndex::City.import!(old_objects) }
386
+ before { CitiesIndex.import!(old_objects) }
368
387
 
369
388
  specify do
370
389
  payload = subscribe_notification
@@ -374,7 +393,7 @@ describe Chewy::Type::Import do
374
393
 
375
394
  expect(payload).to eq(
376
395
  import: {index: 6},
377
- type: CitiesIndex::City
396
+ index: CitiesIndex
378
397
  )
379
398
  expect(imported_cities).to match_array([
380
399
  {'id' => '1', 'name' => 'Name11', 'object' => {'foo' => 1}},
@@ -388,7 +407,7 @@ describe Chewy::Type::Import do
388
407
  end
389
408
 
390
409
  context do
391
- before { CitiesIndex::City.import!(old_objects) }
410
+ before { CitiesIndex.import!(old_objects) }
392
411
 
393
412
  specify do
394
413
  payload = subscribe_notification
@@ -397,9 +416,14 @@ describe Chewy::Type::Import do
397
416
  import(objects, update_fields: %i[object])
398
417
 
399
418
  expect(payload).to eq(
400
- errors: {update: {{'type' => 'mapper_parsing_exception', 'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'} => %w[2 4]}},
419
+ errors: {
420
+ update: {{
421
+ 'type' => 'mapper_parsing_exception',
422
+ 'reason' => 'object mapping for [object] tried to parse field [object] as object, but found a concrete value'
423
+ } => %w[2 4]}
424
+ },
401
425
  import: {index: 6},
402
- type: CitiesIndex::City
426
+ index: CitiesIndex
403
427
  )
404
428
  expect(imported_cities).to match_array([
405
429
  {'id' => '1', 'name' => 'Name1', 'object' => {'foo' => 11}},
@@ -417,9 +441,8 @@ describe Chewy::Type::Import do
417
441
  context do
418
442
  before do
419
443
  stub_index(:cities) do
420
- define_type City do
421
- field :name, type: 'object'
422
- end
444
+ index_scope City
445
+ field :name, type: 'object'
423
446
  end
424
447
  end
425
448
 
@@ -431,9 +454,8 @@ describe Chewy::Type::Import do
431
454
  context do
432
455
  before do
433
456
  stub_index(:cities) do
434
- define_type City do
435
- field :name, type: 'object', value: -> { name == 'name1' ? name : {name: name} }
436
- end
457
+ index_scope City
458
+ field :name, type: 'object', value: -> { name == 'name1' ? name : {name: name} }
437
459
  end
438
460
  end
439
461
 
@@ -445,19 +467,19 @@ describe Chewy::Type::Import do
445
467
 
446
468
  context 'default_import_options are set' do
447
469
  before do
448
- CitiesIndex::City.default_import_options(batch_size: 500)
470
+ CitiesIndex.default_import_options(batch_size: 500)
449
471
  end
450
472
 
451
473
  specify do
452
- expect(CitiesIndex::City.adapter).to receive(:import).with(any_args, hash_including(batch_size: 500))
453
- CitiesIndex::City.import
474
+ expect(CitiesIndex.adapter).to receive(:import).with(any_args, hash_including(batch_size: 500))
475
+ CitiesIndex.import
454
476
  end
455
477
  end
456
478
  end
457
479
 
458
480
  describe '.import', :orm do
459
481
  def import(*args)
460
- CitiesIndex::City.import(*args)
482
+ CitiesIndex.import(*args)
461
483
  end
462
484
 
463
485
  it_behaves_like 'importing'
@@ -466,62 +488,99 @@ describe Chewy::Type::Import do
466
488
  def import(*args)
467
489
  options = args.extract_options!
468
490
  options[:parallel] = 0
469
- CitiesIndex::City.import(*args, options)
491
+ CitiesIndex.import(*args, options)
470
492
  end
471
493
 
472
494
  it_behaves_like 'importing'
473
495
  end
496
+
497
+ context 'with parent-child relationship' do
498
+ before do
499
+ stub_model(:comment)
500
+ stub_index(:comments) do
501
+ index_scope Comment
502
+ field :content
503
+ field :comment_type, type: :join, relations: {question: %i[answer comment], answer: :vote}, join: {type: :comment_type, id: :commented_id}
504
+ end
505
+ end
506
+
507
+ let!(:comments) do
508
+ [
509
+ Comment.create!(id: 1, content: 'Where is Nemo?', comment_type: :question),
510
+ Comment.create!(id: 2, content: 'Here.', comment_type: :answer, commented_id: 1),
511
+ Comment.create!(id: 3, content: 'There!', comment_type: :answer, commented_id: 1),
512
+ Comment.create!(id: 4, content: 'Yes, he is here.', comment_type: :vote, commented_id: 2)
513
+ ]
514
+ end
515
+
516
+ def imported_comments
517
+ CommentsIndex.all.map do |comment|
518
+ comment.attributes.except('_score', '_explanation')
519
+ end
520
+ end
521
+
522
+ it 'imports parent and children' do
523
+ CommentsIndex.import!(comments.map(&:id))
524
+
525
+ expect(imported_comments).to match_array([
526
+ {'id' => '1', 'content' => 'Where is Nemo?', 'comment_type' => 'question'},
527
+ {'id' => '2', 'content' => 'Here.', 'comment_type' => {'name' => 'answer', 'parent' => 1}},
528
+ {'id' => '3', 'content' => 'There!', 'comment_type' => {'name' => 'answer', 'parent' => 1}},
529
+ {'id' => '4', 'content' => 'Yes, he is here.', 'comment_type' => {'name' => 'vote', 'parent' => 2}}
530
+ ])
531
+
532
+ answer_ids = CommentsIndex.query(has_parent: {parent_type: 'question', query: {match: {content: 'Where'}}}).pluck(:_id)
533
+ expect(answer_ids).to match_array(%w[2 3])
534
+ end
535
+ end
474
536
  end
475
537
 
476
538
  describe '.import!', :orm do
477
- specify { expect { CitiesIndex::City.import! }.not_to raise_error }
539
+ specify { expect { CitiesIndex.import! }.not_to raise_error }
478
540
 
479
541
  context do
480
542
  before do
481
543
  stub_index(:cities) do
482
- define_type City do
483
- field :name, type: 'object'
484
- end
544
+ index_scope City
545
+ field :name, type: 'object'
485
546
  end
486
547
  end
487
548
 
488
- specify { expect { CitiesIndex::City.import!(dummy_cities) }.to raise_error Chewy::ImportFailed }
549
+ specify { expect { CitiesIndex.import!(dummy_cities) }.to raise_error Chewy::ImportFailed }
489
550
  end
490
551
  end
491
552
 
492
553
  describe '.compose' do
493
554
  before do
494
555
  stub_index(:cities) do
495
- define_type :city do
496
- crutch :names do |collection|
497
- collection.map { |o| [o.name, o.name + '42'] }.to_h
498
- end
499
- field :name, value: ->(o, c) { c.names[o.name] }
500
- field :rating
556
+ crutch :names do |collection|
557
+ collection.map { |o| [o.name, "#{o.name}42"] }.to_h
501
558
  end
559
+ field :name, value: ->(o, c) { c.names[o.name] }
560
+ field :rating
502
561
  end
503
562
  end
504
563
 
505
564
  specify do
506
- expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42)))
565
+ expect(CitiesIndex.compose(double(name: 'Name', rating: 42)))
507
566
  .to eq('name' => 'Name42', 'rating' => 42)
508
567
  end
509
568
 
510
569
  specify do
511
- expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42), fields: %i[name]))
570
+ expect(CitiesIndex.compose(double(name: 'Name', rating: 42), fields: %i[name]))
512
571
  .to eq('name' => 'Name42')
513
572
  end
514
573
 
515
574
  context 'witchcraft' do
516
- before { CitiesIndex::City.witchcraft! }
575
+ before { CitiesIndex.witchcraft! }
517
576
 
518
577
  specify do
519
- expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42)))
578
+ expect(CitiesIndex.compose(double(name: 'Name', rating: 42)))
520
579
  .to eq('name' => 'Name42', 'rating' => 42)
521
580
  end
522
581
 
523
582
  specify do
524
- expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42), fields: %i[name]))
583
+ expect(CitiesIndex.compose(double(name: 'Name', rating: 42), fields: %i[name]))
525
584
  .to eq('name' => 'Name42')
526
585
  end
527
586
  end
@@ -530,12 +589,12 @@ describe Chewy::Type::Import do
530
589
  let(:crutches) { double(names: {'Name' => 'Name43'}) }
531
590
 
532
591
  specify do
533
- expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42), crutches))
592
+ expect(CitiesIndex.compose(double(name: 'Name', rating: 42), crutches))
534
593
  .to eq('name' => 'Name43', 'rating' => 42)
535
594
  end
536
595
 
537
596
  specify do
538
- expect(CitiesIndex::City.compose(double(name: 'Name', rating: 42), crutches, fields: %i[name]))
597
+ expect(CitiesIndex.compose(double(name: 'Name', rating: 42), crutches, fields: %i[name]))
539
598
  .to eq('name' => 'Name43')
540
599
  end
541
600
  end