elasticsearch-model 6.0.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +5 -0
- data/README.md +14 -7
- data/Rakefile +27 -36
- data/elasticsearch-model.gemspec +1 -1
- data/examples/activerecord_mapping_completion.rb +2 -15
- data/gemfiles/3.0.gemfile +6 -1
- data/gemfiles/4.0.gemfile +7 -1
- data/gemfiles/5.0.gemfile +6 -0
- data/lib/elasticsearch/model.rb +15 -8
- data/lib/elasticsearch/model/adapters/active_record.rb +7 -26
- data/lib/elasticsearch/model/indexing.rb +5 -3
- data/lib/elasticsearch/model/naming.rb +6 -1
- data/lib/elasticsearch/model/response.rb +2 -2
- data/lib/elasticsearch/model/response/pagination.rb +2 -192
- data/lib/elasticsearch/model/response/pagination/kaminari.rb +109 -0
- data/lib/elasticsearch/model/response/pagination/will_paginate.rb +95 -0
- data/lib/elasticsearch/model/response/result.rb +1 -1
- data/lib/elasticsearch/model/version.rb +1 -1
- data/spec/elasticsearch/model/adapter_spec.rb +119 -0
- data/spec/elasticsearch/model/adapters/active_record/associations_spec.rb +334 -0
- data/spec/elasticsearch/model/adapters/active_record/basic_spec.rb +340 -0
- data/spec/elasticsearch/model/adapters/active_record/dynamic_index_name_spec.rb +18 -0
- data/spec/elasticsearch/model/adapters/active_record/import_spec.rb +187 -0
- data/spec/elasticsearch/model/adapters/active_record/multi_model_spec.rb +110 -0
- data/spec/elasticsearch/model/adapters/active_record/namespaced_model_spec.rb +38 -0
- data/spec/elasticsearch/model/adapters/active_record/pagination_spec.rb +315 -0
- data/spec/elasticsearch/model/adapters/active_record/parent_child_spec.rb +75 -0
- data/spec/elasticsearch/model/adapters/active_record/serialization_spec.rb +61 -0
- data/spec/elasticsearch/model/adapters/active_record_spec.rb +207 -0
- data/spec/elasticsearch/model/adapters/default_spec.rb +41 -0
- data/spec/elasticsearch/model/adapters/mongoid/basic_spec.rb +267 -0
- data/spec/elasticsearch/model/adapters/mongoid/multi_model_spec.rb +66 -0
- data/spec/elasticsearch/model/adapters/mongoid_spec.rb +235 -0
- data/spec/elasticsearch/model/adapters/multiple_spec.rb +125 -0
- data/spec/elasticsearch/model/callbacks_spec.rb +33 -0
- data/spec/elasticsearch/model/client_spec.rb +66 -0
- data/spec/elasticsearch/model/hash_wrapper_spec.rb +12 -0
- data/spec/elasticsearch/model/importing_spec.rb +214 -0
- data/spec/elasticsearch/model/indexing_spec.rb +918 -0
- data/spec/elasticsearch/model/module_spec.rb +101 -0
- data/spec/elasticsearch/model/multimodel_spec.rb +55 -0
- data/spec/elasticsearch/model/naming_inheritance_spec.rb +184 -0
- data/spec/elasticsearch/model/naming_spec.rb +186 -0
- data/spec/elasticsearch/model/proxy_spec.rb +107 -0
- data/spec/elasticsearch/model/response/aggregations_spec.rb +66 -0
- data/spec/elasticsearch/model/response/base_spec.rb +90 -0
- data/spec/elasticsearch/model/response/pagination/kaminari_spec.rb +410 -0
- data/spec/elasticsearch/model/response/pagination/will_paginate_spec.rb +262 -0
- data/spec/elasticsearch/model/response/records_spec.rb +118 -0
- data/spec/elasticsearch/model/response/response_spec.rb +131 -0
- data/spec/elasticsearch/model/response/result_spec.rb +122 -0
- data/spec/elasticsearch/model/response/results_spec.rb +56 -0
- data/spec/elasticsearch/model/searching_search_request_spec.rb +112 -0
- data/spec/elasticsearch/model/searching_spec.rb +49 -0
- data/spec/elasticsearch/model/serializing_spec.rb +22 -0
- data/spec/spec_helper.rb +161 -0
- data/spec/support/app.rb +21 -0
- data/spec/support/app/answer.rb +33 -0
- data/spec/support/app/article.rb +22 -0
- data/spec/support/app/article_for_pagination.rb +12 -0
- data/spec/support/app/article_with_custom_serialization.rb +13 -0
- data/spec/support/app/article_with_dynamic_index_name.rb +15 -0
- data/spec/support/app/author.rb +9 -0
- data/spec/support/app/authorship.rb +4 -0
- data/spec/support/app/category.rb +3 -0
- data/spec/support/app/comment.rb +3 -0
- data/spec/support/app/episode.rb +11 -0
- data/spec/support/app/image.rb +19 -0
- data/spec/support/app/import_article.rb +12 -0
- data/spec/support/app/mongoid_article.rb +21 -0
- data/spec/support/app/namespaced_book.rb +10 -0
- data/spec/support/app/parent_and_child_searchable.rb +24 -0
- data/spec/support/app/post.rb +14 -0
- data/spec/support/app/question.rb +27 -0
- data/spec/support/app/searchable.rb +48 -0
- data/spec/support/app/series.rb +11 -0
- data/spec/support/model.json +1 -0
- data/{test → spec}/support/model.yml +0 -0
- metadata +129 -86
- data/test/integration/active_record_associations_parent_child_test.rb +0 -188
- data/test/integration/active_record_associations_test.rb +0 -339
- data/test/integration/active_record_basic_test.rb +0 -255
- data/test/integration/active_record_custom_serialization_test.rb +0 -67
- data/test/integration/active_record_import_test.rb +0 -168
- data/test/integration/active_record_namespaced_model_test.rb +0 -56
- data/test/integration/active_record_pagination_test.rb +0 -149
- data/test/integration/dynamic_index_name_test.rb +0 -52
- data/test/integration/mongoid_basic_test.rb +0 -240
- data/test/integration/multiple_models_test.rb +0 -176
- data/test/support/model.json +0 -1
- data/test/test_helper.rb +0 -92
- data/test/unit/adapter_active_record_test.rb +0 -157
- data/test/unit/adapter_default_test.rb +0 -41
- data/test/unit/adapter_mongoid_test.rb +0 -161
- data/test/unit/adapter_multiple_test.rb +0 -106
- data/test/unit/adapter_test.rb +0 -69
- data/test/unit/callbacks_test.rb +0 -31
- data/test/unit/client_test.rb +0 -27
- data/test/unit/hash_wrapper_test.rb +0 -13
- data/test/unit/importing_test.rb +0 -224
- data/test/unit/indexing_test.rb +0 -720
- data/test/unit/module_test.rb +0 -68
- data/test/unit/multimodel_test.rb +0 -38
- data/test/unit/naming_inheritance_test.rb +0 -94
- data/test/unit/naming_test.rb +0 -103
- data/test/unit/proxy_test.rb +0 -98
- data/test/unit/response_aggregations_test.rb +0 -46
- data/test/unit/response_base_test.rb +0 -40
- data/test/unit/response_pagination_kaminari_test.rb +0 -433
- data/test/unit/response_pagination_will_paginate_test.rb +0 -398
- data/test/unit/response_records_test.rb +0 -91
- data/test/unit/response_result_test.rb +0 -90
- data/test/unit/response_results_test.rb +0 -34
- data/test/unit/response_test.rb +0 -104
- data/test/unit/searching_search_request_test.rb +0 -78
- data/test/unit/searching_test.rb +0 -41
- data/test/unit/serializing_test.rb +0 -17
@@ -0,0 +1,340 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Elasticsearch::Model::Adapter::ActiveRecord do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
ActiveRecord::Schema.define(:version => 1) do
|
7
|
+
create_table :articles do |t|
|
8
|
+
t.string :title
|
9
|
+
t.string :body
|
10
|
+
t.integer :clicks, :default => 0
|
11
|
+
t.datetime :created_at, :default => 'NOW()'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Article.delete_all
|
16
|
+
Article.__elasticsearch__.create_index!(force: true)
|
17
|
+
|
18
|
+
Article.create!(title: 'Test', body: '', clicks: 1)
|
19
|
+
Article.create!(title: 'Testing Coding', body: '', clicks: 2)
|
20
|
+
Article.create!(title: 'Coding', body: '', clicks: 3)
|
21
|
+
|
22
|
+
Article.__elasticsearch__.refresh_index!
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'indexing a document' do
|
26
|
+
|
27
|
+
let(:search_result) do
|
28
|
+
Article.search('title:test')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'allows searching for documents' do
|
32
|
+
expect(search_result.results.size).to be(2)
|
33
|
+
expect(search_result.records.size).to be(2)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#results' do
|
38
|
+
|
39
|
+
let(:search_result) do
|
40
|
+
Article.search('title:test')
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns an instance of Response::Result' do
|
44
|
+
expect(search_result.results.first).to be_a(Elasticsearch::Model::Response::Result)
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'prooperly loads the document' do
|
48
|
+
expect(search_result.results.first.title).to eq('Test')
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'when the result contains other data' do
|
52
|
+
|
53
|
+
let(:search_result) do
|
54
|
+
Article.search(query: { match: { title: 'test' } }, highlight: { fields: { title: {} } })
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'allows access to the Elasticsearch result' do
|
58
|
+
expect(search_result.results.first.title).to eq('Test')
|
59
|
+
expect(search_result.results.first.title?).to be(true)
|
60
|
+
expect(search_result.results.first.boo?).to be(false)
|
61
|
+
expect(search_result.results.first.highlight?).to be(true)
|
62
|
+
expect(search_result.results.first.highlight.title?).to be(true)
|
63
|
+
expect(search_result.results.first.highlight.boo?).to be(false)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#records' do
|
69
|
+
|
70
|
+
let(:search_result) do
|
71
|
+
Article.search('title:test')
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'returns an instance of the model' do
|
75
|
+
expect(search_result.records.first).to be_a(Article)
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'prooperly loads the document' do
|
79
|
+
expect(search_result.records.first.title).to eq('Test')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe 'Enumerable' do
|
84
|
+
|
85
|
+
let(:search_result) do
|
86
|
+
Article.search('title:test')
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'allows iteration over results' do
|
90
|
+
expect(search_result.results.map(&:_id)).to eq(['1', '2'])
|
91
|
+
end
|
92
|
+
|
93
|
+
it 'allows iteration over records' do
|
94
|
+
expect(search_result.records.map(&:id)).to eq([1, 2])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#id' do
|
99
|
+
|
100
|
+
let(:search_result) do
|
101
|
+
Article.search('title:test')
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'returns the id' do
|
105
|
+
expect(search_result.results.first.id).to eq('1')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#id' do
|
110
|
+
|
111
|
+
let(:search_result) do
|
112
|
+
Article.search('title:test')
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'returns the type' do
|
116
|
+
expect(search_result.results.first.type).to eq('article')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '#each_with_hit' do
|
121
|
+
|
122
|
+
let(:search_result) do
|
123
|
+
Article.search('title:test')
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'returns the record with the Elasticsearch hit' do
|
127
|
+
search_result.records.each_with_hit do |r, h|
|
128
|
+
expect(h._score).not_to be_nil
|
129
|
+
expect(h._source.title).not_to be_nil
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe 'search results order' do
|
135
|
+
|
136
|
+
let(:search_result) do
|
137
|
+
Article.search(query: { match: { title: 'code' }}, sort: { clicks: :desc })
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'preserves the search results order when accessing a single record' do
|
141
|
+
expect(search_result.records[0].clicks).to be(3)
|
142
|
+
expect(search_result.records[1].clicks).to be(2)
|
143
|
+
expect(search_result.records.first).to eq(search_result.records[0])
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'preserves the search results order for the list of records' do
|
147
|
+
search_result.records.each_with_hit do |r, h|
|
148
|
+
expect(r.id.to_s).to eq(h._id)
|
149
|
+
end
|
150
|
+
|
151
|
+
search_result.records.map_with_hit do |r, h|
|
152
|
+
expect(r.id.to_s).to eq(h._id)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
describe 'a paged collection' do
|
158
|
+
|
159
|
+
let(:search_result) do
|
160
|
+
Article.search(query: { match: { title: { query: 'test' } } },
|
161
|
+
size: 2,
|
162
|
+
from: 1)
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'applies the paged options to the search' do
|
166
|
+
expect(search_result.results.size).to eq(1)
|
167
|
+
expect(search_result.results.first.title).to eq('Testing Coding')
|
168
|
+
expect(search_result.records.size).to eq(1)
|
169
|
+
expect(search_result.records.first.title).to eq('Testing Coding')
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe '#destroy' do
|
174
|
+
|
175
|
+
before do
|
176
|
+
Article.create!(title: 'destroy', body: '', clicks: 1)
|
177
|
+
Article.__elasticsearch__.refresh_index!
|
178
|
+
Article.where(title: 'destroy').first.destroy
|
179
|
+
|
180
|
+
Article.__elasticsearch__.refresh_index!
|
181
|
+
end
|
182
|
+
|
183
|
+
let(:search_result) do
|
184
|
+
Article.search('title:test')
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'removes the document from the index' do
|
188
|
+
expect(Article.count).to eq(3)
|
189
|
+
expect(search_result.results.size).to eq(2)
|
190
|
+
expect(search_result.records.size).to eq(2)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
describe 'full document updates' do
|
195
|
+
|
196
|
+
before do
|
197
|
+
article = Article.create!(title: 'update', body: '', clicks: 1)
|
198
|
+
Article.__elasticsearch__.refresh_index!
|
199
|
+
article.title = 'Writing'
|
200
|
+
article.save
|
201
|
+
|
202
|
+
Article.__elasticsearch__.refresh_index!
|
203
|
+
end
|
204
|
+
|
205
|
+
let(:search_result) do
|
206
|
+
Article.search('title:write')
|
207
|
+
end
|
208
|
+
|
209
|
+
it 'applies the update' do
|
210
|
+
expect(search_result.results.size).to eq(1)
|
211
|
+
expect(search_result.records.size).to eq(1)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
describe 'attribute updates' do
|
216
|
+
|
217
|
+
before do
|
218
|
+
article = Article.create!(title: 'update', body: '', clicks: 1)
|
219
|
+
Article.__elasticsearch__.refresh_index!
|
220
|
+
article.title = 'special'
|
221
|
+
article.save
|
222
|
+
|
223
|
+
Article.__elasticsearch__.refresh_index!
|
224
|
+
end
|
225
|
+
|
226
|
+
let(:search_result) do
|
227
|
+
Article.search('title:special')
|
228
|
+
end
|
229
|
+
|
230
|
+
it 'applies the update' do
|
231
|
+
expect(search_result.results.size).to eq(1)
|
232
|
+
expect(search_result.records.size).to eq(1)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
describe '#save' do
|
237
|
+
|
238
|
+
before do
|
239
|
+
article = Article.create!(title: 'save', body: '', clicks: 1)
|
240
|
+
|
241
|
+
ActiveRecord::Base.transaction do
|
242
|
+
article.body = 'dummy'
|
243
|
+
article.save
|
244
|
+
|
245
|
+
article.title = 'special'
|
246
|
+
article.save
|
247
|
+
end
|
248
|
+
|
249
|
+
article.__elasticsearch__.update_document
|
250
|
+
Article.__elasticsearch__.refresh_index!
|
251
|
+
end
|
252
|
+
|
253
|
+
let(:search_result) do
|
254
|
+
Article.search('body:dummy')
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'applies the save' do
|
258
|
+
expect(search_result.results.size).to eq(1)
|
259
|
+
expect(search_result.records.size).to eq(1)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
describe 'a DSL search' do
|
264
|
+
|
265
|
+
let(:search_result) do
|
266
|
+
Article.search(query: { match: { title: { query: 'test' } } })
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'returns the results' do
|
270
|
+
expect(search_result.results.size).to eq(2)
|
271
|
+
expect(search_result.records.size).to eq(2)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
describe 'chaining SQL queries on response.records' do
|
276
|
+
|
277
|
+
let(:search_result) do
|
278
|
+
Article.search(query: { match: { title: { query: 'test' } } })
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'executes the SQL request with the chained query criteria' do
|
282
|
+
expect(search_result.records.size).to eq(2)
|
283
|
+
expect(search_result.records.where(title: 'Test').size).to eq(1)
|
284
|
+
expect(search_result.records.where(title: 'Test').first.title).to eq('Test')
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
describe 'ordering of SQL queries' do
|
289
|
+
|
290
|
+
context 'when order is called on the ActiveRecord query' do
|
291
|
+
|
292
|
+
let(:search_result) do
|
293
|
+
Article.search query: { match: { title: { query: 'test' } } }
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'allows the SQL query to be ordered independent of the Elasticsearch results order', unless: active_record_at_least_4? do
|
297
|
+
expect(search_result.records.order('title DESC').first.title).to eq('Testing Coding')
|
298
|
+
expect(search_result.records.order('title DESC')[0].title).to eq('Testing Coding')
|
299
|
+
end
|
300
|
+
|
301
|
+
it 'allows the SQL query to be ordered independent of the Elasticsearch results order', if: active_record_at_least_4? do
|
302
|
+
expect(search_result.records.order(title: :desc).first.title).to eq('Testing Coding')
|
303
|
+
expect(search_result.records.order(title: :desc)[0].title).to eq('Testing Coding')
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
context 'when more methods are chained on the ActiveRecord query' do
|
308
|
+
|
309
|
+
let(:search_result) do
|
310
|
+
Article.search query: {match: {title: {query: 'test'}}}
|
311
|
+
end
|
312
|
+
|
313
|
+
it 'allows the SQL query to be ordered independent of the Elasticsearch results order', if: active_record_at_least_4? do
|
314
|
+
expect(search_result.records.distinct.order(title: :desc).first.title).to eq('Testing Coding')
|
315
|
+
expect(search_result.records.distinct.order(title: :desc)[0].title).to eq('Testing Coding')
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
319
|
+
|
320
|
+
describe 'access to the response via methods' do
|
321
|
+
|
322
|
+
let(:search_result) do
|
323
|
+
Article.search(query: { match: { title: { query: 'test' } } },
|
324
|
+
aggregations: {
|
325
|
+
dates: { date_histogram: { field: 'created_at', interval: 'hour' } },
|
326
|
+
clicks: { global: {}, aggregations: { min: { min: { field: 'clicks' } } } }
|
327
|
+
},
|
328
|
+
suggest: { text: 'tezt', title: { term: { field: 'title', suggest_mode: 'always' } } })
|
329
|
+
end
|
330
|
+
|
331
|
+
it 'allows document keys to be access via methods' do
|
332
|
+
expect(search_result.aggregations.dates.buckets.first.doc_count).to eq(2)
|
333
|
+
expect(search_result.aggregations.clicks.doc_count).to eq(6)
|
334
|
+
expect(search_result.aggregations.clicks.min.value).to eq(1.0)
|
335
|
+
expect(search_result.aggregations.clicks.max).to be_nil
|
336
|
+
expect(search_result.suggestions.title.first.options.size).to eq(1)
|
337
|
+
expect(search_result.suggestions.terms).to eq(['test'])
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Elasticsearch::Model::Adapter::ActiveRecord Dynamic Index naming' do
|
4
|
+
|
5
|
+
before do
|
6
|
+
ArticleWithDynamicIndexName.counter = 0
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'exavlues the index_name value' do
|
10
|
+
expect(ArticleWithDynamicIndexName.index_name).to eq('articles-1')
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'revaluates the index name with each call' do
|
14
|
+
expect(ArticleWithDynamicIndexName.index_name).to eq('articles-1')
|
15
|
+
expect(ArticleWithDynamicIndexName.index_name).to eq('articles-2')
|
16
|
+
expect(ArticleWithDynamicIndexName.index_name).to eq('articles-3')
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Elasticsearch::Model::Adapter::ActiveRecord Importing' do
|
4
|
+
|
5
|
+
before(:all) do
|
6
|
+
ActiveRecord::Schema.define(:version => 1) do
|
7
|
+
create_table :import_articles do |t|
|
8
|
+
t.string :title
|
9
|
+
t.integer :views
|
10
|
+
t.string :numeric # For the sake of invalid data sent to Elasticsearch
|
11
|
+
t.datetime :created_at, :default => 'NOW()'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
ImportArticle.delete_all
|
16
|
+
ImportArticle.__elasticsearch__.client.cluster.health(wait_for_status: 'yellow')
|
17
|
+
end
|
18
|
+
|
19
|
+
before do
|
20
|
+
ImportArticle.__elasticsearch__.create_index!
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
clear_indices(ImportArticle)
|
25
|
+
clear_tables(ImportArticle)
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#import' do
|
29
|
+
|
30
|
+
context 'when no search criteria is specified' do
|
31
|
+
|
32
|
+
before do
|
33
|
+
10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
|
34
|
+
ImportArticle.import
|
35
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'imports all documents' do
|
39
|
+
expect(ImportArticle.search('*').results.total).to eq(10)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'when batch size is specified' do
|
44
|
+
|
45
|
+
before do
|
46
|
+
10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
|
47
|
+
end
|
48
|
+
|
49
|
+
let!(:batch_count) do
|
50
|
+
batches = 0
|
51
|
+
errors = ImportArticle.import(batch_size: 5) do |response|
|
52
|
+
batches += 1
|
53
|
+
end
|
54
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
55
|
+
batches
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'imports using the batch size' do
|
59
|
+
expect(batch_count).to eq(2)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'imports all the documents' do
|
63
|
+
expect(ImportArticle.search('*').results.total).to eq(10)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'when a scope is specified' do
|
68
|
+
|
69
|
+
before do
|
70
|
+
10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
|
71
|
+
ImportArticle.import(scope: 'popular', force: true)
|
72
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'applies the scope' do
|
76
|
+
expect(ImportArticle.search('*').results.total).to eq(5)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when a query is specified' do
|
81
|
+
|
82
|
+
before do
|
83
|
+
10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
|
84
|
+
ImportArticle.import(query: -> { where('views >= 3') })
|
85
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'applies the query' do
|
89
|
+
expect(ImportArticle.search('*').results.total).to eq(7)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when there are invalid documents' do
|
94
|
+
|
95
|
+
let!(:result) do
|
96
|
+
10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
|
97
|
+
new_article
|
98
|
+
batches = 0
|
99
|
+
errors = ImportArticle.__elasticsearch__.import(batch_size: 5) do |response|
|
100
|
+
batches += 1
|
101
|
+
end
|
102
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
103
|
+
{ batch_size: batches, errors: errors}
|
104
|
+
end
|
105
|
+
|
106
|
+
let(:new_article) do
|
107
|
+
ImportArticle.create!(title: "Test INVALID", numeric: "INVALID")
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'does not import them' do
|
111
|
+
expect(ImportArticle.search('*').results.total).to eq(10)
|
112
|
+
expect(result[:batch_size]).to eq(3)
|
113
|
+
expect(result[:errors]).to eq(1)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'when a transform proc is specified' do
|
118
|
+
|
119
|
+
before do
|
120
|
+
10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
|
121
|
+
ImportArticle.import( transform: ->(a) {{ index: { data: { name: a.title, foo: 'BAR' } }}} )
|
122
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'transforms the documents' do
|
126
|
+
expect(ImportArticle.search('*').results.first._source.keys).to include('name')
|
127
|
+
expect(ImportArticle.search('*').results.first._source.keys).to include('foo')
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'imports all documents' do
|
131
|
+
expect(ImportArticle.search('test').results.total).to eq(10)
|
132
|
+
expect(ImportArticle.search('bar').results.total).to eq(10)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
context 'when the model has a default scope' do
|
137
|
+
|
138
|
+
around(:all) do |example|
|
139
|
+
10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
|
140
|
+
ImportArticle.instance_eval { default_scope { where('views > 3') } }
|
141
|
+
example.run
|
142
|
+
ImportArticle.default_scopes.pop
|
143
|
+
end
|
144
|
+
|
145
|
+
before do
|
146
|
+
ImportArticle.__elasticsearch__.import
|
147
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'uses the default scope' do
|
151
|
+
expect(ImportArticle.search('*').results.total).to eq(6)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
context 'when there is a default scope and a query specified' do
|
156
|
+
|
157
|
+
around(:all) do |example|
|
158
|
+
10.times { |i| ImportArticle.create! title: 'Test', views: "#{i}" }
|
159
|
+
ImportArticle.instance_eval { default_scope { where('views > 3') } }
|
160
|
+
example.run
|
161
|
+
ImportArticle.default_scopes.pop
|
162
|
+
end
|
163
|
+
|
164
|
+
before do
|
165
|
+
ImportArticle.import(query: -> { where('views <= 4') })
|
166
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'combines the query and the default scope' do
|
170
|
+
expect(ImportArticle.search('*').results.total).to eq(1)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context 'when the batch is empty' do
|
175
|
+
|
176
|
+
before do
|
177
|
+
ImportArticle.delete_all
|
178
|
+
ImportArticle.import
|
179
|
+
ImportArticle.__elasticsearch__.refresh_index!
|
180
|
+
end
|
181
|
+
|
182
|
+
it 'does not make any requests to create documents' do
|
183
|
+
expect(ImportArticle.search('*').results.total).to eq(0)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|