elasticated 2.5.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +35 -2
  3. data/Rakefile +52 -1
  4. data/elasticated.gemspec +3 -1
  5. data/lib/elasticated.rb +20 -24
  6. data/lib/elasticated/aggregation.rb +3 -6
  7. data/lib/elasticated/aggregations/date_histogram_aggregation.rb +6 -1
  8. data/lib/elasticated/aggregations/filter_aggregation.rb +8 -12
  9. data/lib/elasticated/aggregations/filter_aggregation_evaluator.rb +1 -1
  10. data/lib/elasticated/aggregations/group_aggregation.rb +14 -11
  11. data/lib/elasticated/aggregations/range_aggregation.rb +10 -11
  12. data/lib/elasticated/aggregations/range_aggregation_evaluator.rb +1 -1
  13. data/lib/elasticated/aggregations/ranges_builder.rb +2 -2
  14. data/lib/elasticated/aggregations/safe_date_histogram_aggregation.rb +7 -2
  15. data/lib/elasticated/aggregations/subaggregated.rb +1 -1
  16. data/lib/elasticated/boolean_clause.rb +4 -3
  17. data/lib/elasticated/bulk_actions/create_action.rb +14 -0
  18. data/lib/elasticated/bulk_actions/delete_action.rb +30 -0
  19. data/lib/elasticated/bulk_actions/index_action.rb +35 -0
  20. data/lib/elasticated/bulk_actions/standard_action.rb +22 -0
  21. data/lib/elasticated/bulk_actions/update_action.rb +44 -0
  22. data/lib/elasticated/bulk_actions/upsert_action.rb +14 -0
  23. data/lib/elasticated/bulk_request.rb +58 -0
  24. data/lib/elasticated/bulk_request/response.rb +32 -0
  25. data/lib/elasticated/bulk_request/response_item.rb +39 -0
  26. data/lib/elasticated/client.rb +27 -3
  27. data/lib/elasticated/conditions/custom_condition.rb +3 -3
  28. data/lib/elasticated/conditions/range_condition.rb +5 -2
  29. data/lib/elasticated/conditions/script_condition.rb +3 -3
  30. data/lib/elasticated/conditions/standard_condition.rb +4 -5
  31. data/lib/elasticated/conditions/term_condition.rb +22 -0
  32. data/lib/elasticated/conditions/terms_condition.rb +2 -2
  33. data/lib/elasticated/conditions_builder.rb +19 -4
  34. data/lib/elasticated/delimiters/date_field_delimiter.rb +21 -12
  35. data/lib/elasticated/delimiters/standard_field_delimiter.rb +18 -2
  36. data/lib/elasticated/delimiters/term_field_delimiter.rb +6 -5
  37. data/lib/elasticated/document.rb +20 -1
  38. data/lib/elasticated/enum.rb +17 -0
  39. data/lib/elasticated/index_selector.rb +26 -25
  40. data/lib/elasticated/mapping.rb +2 -4
  41. data/lib/elasticated/mapping/builder.rb +3 -2
  42. data/lib/elasticated/mapping/fields_builder.rb +13 -9
  43. data/lib/elasticated/mapping/object_builder.rb +38 -4
  44. data/lib/elasticated/mapping/type_builder.rb +3 -5
  45. data/lib/elasticated/mixins/block_evaluation.rb +17 -0
  46. data/lib/elasticated/mixins/clonable.rb +60 -0
  47. data/lib/elasticated/mixins/configurable.rb +22 -0
  48. data/lib/elasticated/mixins/inspectionable.rb +16 -0
  49. data/lib/elasticated/partitioned_repository.rb +24 -18
  50. data/lib/elasticated/query.rb +27 -21
  51. data/lib/elasticated/query_aggregations.rb +5 -7
  52. data/lib/elasticated/query_conditions.rb +6 -3
  53. data/lib/elasticated/quick.rb +7 -0
  54. data/lib/elasticated/repository.rb +184 -40
  55. data/lib/elasticated/repository/intelligent_search.rb +3 -3
  56. data/lib/elasticated/repository/normal_search.rb +2 -2
  57. data/lib/elasticated/repository/resumable_search.rb +5 -5
  58. data/lib/elasticated/repository/scan_scroll_search.rb +4 -4
  59. data/lib/elasticated/repository/scroll_search.rb +3 -3
  60. data/lib/elasticated/repository/search.rb +7 -0
  61. data/lib/elasticated/repository/single_page_search.rb +1 -1
  62. data/lib/elasticated/results.rb +14 -0
  63. data/lib/version.rb +18 -25
  64. data/spec/aggregation_spec.rb +95 -16
  65. data/spec/bulk_request_spec.rb +158 -0
  66. data/spec/date_field_delimiter_spec.rb +50 -6
  67. data/spec/document_spec.rb +1 -5
  68. data/spec/integration_spec.rb +7 -7
  69. data/spec/mapping_spec.rb +128 -8
  70. data/spec/partitioned_repository_spec.rb +218 -0
  71. data/spec/query_conditions_spec.rb +98 -45
  72. data/spec/query_spec.rb +21 -28
  73. data/spec/repository_spec.rb +245 -0
  74. data/spec/results_spec.rb +0 -4
  75. data/spec/sample_responses/elasticsearch_bulk_response_1.json +35 -0
  76. data/spec/sample_responses/elasticsearch_bulk_response_2.json +20 -0
  77. data/spec/sample_responses/elasticsearch_count_1.json +8 -0
  78. data/spec/sample_responses/elasticsearch_count_2.json +8 -0
  79. data/spec/sample_responses/elasticsearch_get_response_1.json +10 -0
  80. data/spec/sample_responses/elasticsearch_get_response_2.json +6 -0
  81. data/spec/{elasticsearch_hit_1.json → sample_responses/elasticsearch_hit_1.json} +0 -0
  82. data/spec/sample_responses/elasticsearch_mget_response_1.json +25 -0
  83. data/spec/{elasticsearch_response_1.json → sample_responses/elasticsearch_response_1.json} +0 -0
  84. data/spec/{elasticsearch_response_2.json → sample_responses/elasticsearch_response_2.json} +0 -0
  85. data/spec/{elasticsearch_top_hits_response.json → sample_responses/elasticsearch_top_hits_response.json} +0 -0
  86. data/spec/spec_helper.rb +47 -0
  87. data/spec/spec_helper/fake_index_selector.rb +27 -0
  88. data/spec/term_field_delimiter_spec.rb +8 -8
  89. metadata +80 -26
  90. data/lib/elasticated/block_evaluation.rb +0 -15
  91. data/lib/elasticated/clonable.rb +0 -58
  92. data/lib/elasticated/configurable.rb +0 -20
  93. data/lib/elasticated/date_delimiter_factory.rb +0 -123
  94. data/lib/elasticated/delimiter_visitor.rb +0 -53
  95. data/lib/elasticated/inspectionable.rb +0 -9
  96. data/lib/elasticated/strategy_params_for_query_service.rb +0 -14
  97. data/lib/elasticated/term_delimiter_factory.rb +0 -73
  98. data/spec/delimiter_factory_spec.rb +0 -399
  99. data/spec/strategy_params_for_query_service_spec.rb +0 -387
@@ -13,20 +13,26 @@ module Elasticated
13
13
  end
14
14
 
15
15
  it "should build a 'terms' condition" do
16
- qc.equal :field, :value
17
- expected_result = { terms: { field: [:value] } }
16
+ qc.terms :field, [:value1, :value2]
17
+ expected_result = { terms: { field: [:value1, :value2] } }
18
+ expect(qc.build).to eq expected_result
19
+ end
20
+
21
+ it "should build a 'terms' condition (with the 'equal' alias)" do
22
+ qc.equal :field, [:value1, :value2]
23
+ expected_result = { terms: { field: [:value1, :value2] } }
18
24
  expect(qc.build).to eq expected_result
19
25
  end
20
26
 
21
27
  it "should build a 'terms' condition (with params)" do
22
- qc.equal :field, :value, execution: :bool, _cache: false
23
- expected_result = { terms: { field: [:value], execution: :bool, _cache: false } }
28
+ qc.terms :field, [:value1, :value2], execution: :bool, _cache: false
29
+ expected_result = { terms: { field: [:value1, :value2], execution: :bool, _cache: false } }
24
30
  expect(qc.build).to eq expected_result
25
31
  end
26
32
 
27
33
  it "should build a 'must_not>terms' condition" do
28
- qc.not_equal :field, :value
29
- expected_result = { bool: { must_not: [ { terms: { field: [:value] } } ] } }
34
+ qc.not_equal :field, [:value1, :value2]
35
+ expected_result = { bool: { must_not: [ { terms: { field: [:value1, :value2] } } ] } }
30
36
  expect(qc.build).to eq expected_result
31
37
  end
32
38
 
@@ -66,6 +72,12 @@ module Elasticated
66
72
  expect(qc.build).to eq expected_result
67
73
  end
68
74
 
75
+ it "should build a 'between' condition (using the 'range' alias)" do
76
+ qc.range :field, :min_value, :max_value
77
+ expected_result = { range: { field: { gte: :min_value, lte: :max_value } } }
78
+ expect(qc.build).to eq expected_result
79
+ end
80
+
69
81
  it "should build a 'greater_than' condition" do
70
82
  qc.greater_than :field, :min_value
71
83
  expected_result = { range: { field: { gt: :min_value } } }
@@ -122,50 +134,32 @@ module Elasticated
122
134
 
123
135
  it "should build a 'nested' condition" do
124
136
  qc.nested :hash do |n|
125
- n.equal :field, :value
137
+ n.term :field, :value
126
138
  end
127
- expected_result = { nested: { path: :hash, filter: { terms: { field: [:value] } } } }
139
+ expected_result = { nested: { path: :hash, filter: { term: { field: :value } } } }
128
140
  expect(qc.build).to eq expected_result
129
141
  end
130
142
 
131
143
  it "should build a 'nested' condition (with params)" do
132
144
  qc.nested :hash, _cache: true do |n|
133
- n.equal :field, :value
145
+ n.term :field, :value
134
146
  end
135
- expected_result = { nested: { path: :hash, _cache: true, filter: { terms: { field: [:value] } } } }
147
+ expected_result = { nested: { path: :hash, _cache: true, filter: { term: { field: :value } } } }
136
148
  expect(qc.build).to eq expected_result
137
149
  end
138
150
 
139
- # it "should build a 'should_equal' condition" do
140
- # qc.should_equal :field, :value
141
- # expected_result = { bool: { should: [ { terms: { field: [:value] } } ] } }
142
- # expect(qc.build).to eq expected_result
143
- # end
144
-
145
- # it "should build a 'should_wildcard' condition" do
146
- # qc.should_wildcard :field, 'regex'
147
- # expected_result = { bool: { should: [ { wildcard: { field: 'regex' } } ] } }
148
- # expect(qc.build).to eq expected_result
149
- # end
150
-
151
- # it "should build a 'should_with' condition" do
152
- # qc.should_with :field
153
- # expected_result = { bool: { should: [ { wildcard: { field: '*' } } ] } }
154
- # expect(qc.build).to eq expected_result
155
- # end
156
-
157
151
  it "should build a 'bool>must' condition" do
158
152
  qc.exists :field
159
- qc.equal :field, :value
160
- expected_result = { bool: { must: [ { exists: { field: :field } }, { terms: { field: [:value] } } ] } }
153
+ qc.term :field, :value
154
+ expected_result = { bool: { must: [ { exists: { field: :field } }, { term: { field: :value } } ] } }
161
155
  expect(qc.build).to eq expected_result
162
156
  end
163
157
 
164
158
  it "should build a 'bool>must' cached condition" do
165
159
  qc.exists :field
166
- qc.equal :field, :value
160
+ qc.term :field, :value
167
161
  qc.cache
168
- expected_result = { bool: { must: [ { exists: { field: :field } }, { terms: { field: [:value] } } ], _cache: true } }
162
+ expected_result = { bool: { must: [ { exists: { field: :field } }, { term: { field: :value } } ], _cache: true } }
169
163
  expect(qc.build).to eq expected_result
170
164
  end
171
165
 
@@ -175,9 +169,9 @@ module Elasticated
175
169
  qc.should{ equal :field_three, :value_three }
176
170
  qc.minimum_should_match 2
177
171
  expected_result = { bool: {
178
- must: [ {terms: { field_one: [:value_one] } } ],
179
- must_not: [ { terms: { field_two: [:value_two] } } ],
180
- should: [ { terms: { field_three: [:value_three] } } ],
172
+ must: [ {term: { field_one: :value_one } } ],
173
+ must_not: [ { term: { field_two: :value_two } } ],
174
+ should: [ { term: { field_three: :value_three } } ],
181
175
  minimum_should_match: 2
182
176
  } }
183
177
  expect(qc.build).to eq expected_result
@@ -190,11 +184,11 @@ module Elasticated
190
184
  expected_result = {
191
185
  bool: {
192
186
  must: [
193
- { terms: { age: [19] } }
187
+ { term: { age: 19 } }
194
188
  ],
195
189
  should: [
196
- { terms: { name: ['Pablo'] } },
197
- { terms: { name: ['Santiago'] } }
190
+ { term: { name: 'Pablo' } },
191
+ { term: { name: 'Santiago' } }
198
192
  ]
199
193
  }
200
194
  }
@@ -213,13 +207,13 @@ module Elasticated
213
207
  expected_result = {
214
208
  bool: {
215
209
  should: [
216
- { terms: { first_name: ['Pablo'] } },
217
- { terms: { last_name: ['Fernandez'] } },
210
+ { term: { first_name: 'Pablo' } },
211
+ { term: { last_name: 'Fernandez' } },
218
212
  {
219
213
  bool: {
220
214
  must: [
221
- { terms: { age: [24] } },
222
- { terms: { country: ['Argentina'] } }
215
+ { term: { age: 24 } },
216
+ { term: { country: 'Argentina' } }
223
217
  ]
224
218
  }
225
219
  }
@@ -242,14 +236,73 @@ module Elasticated
242
236
  qc.not_equal :field_five, :value_five
243
237
  qc.should{ equal :field_six, :value_six }
244
238
  expected_result = { bool: {
245
- must: [ {terms: { field_one: [:value_one] } } ],
246
- must_not: [ { terms: { field_two: [:value_two] } } ],
247
- should: [ { terms: { field_three: [:value_three] } } ]
239
+ must: [ {term: { field_one: :value_one } } ],
240
+ must_not: [ { term: { field_two: :value_two } } ],
241
+ should: [ { term: { field_three: :value_three } } ]
248
242
  } }
249
243
  expect(new_qc.build).to eq expected_result
250
244
  end
251
245
 
252
246
  end
253
247
 
248
+ describe "the term delimiter" do
249
+
250
+ let :delimiter do
251
+ Delimiters::TermFieldDelimiter.new field: :account_id, as: :account
252
+ end
253
+
254
+ it "should not delimit anything" do
255
+ qc.equal :other_field, 68
256
+ qc.fill_delimiter delimiter
257
+ params = delimiter.build_strategy_params
258
+ expect(params).to be_empty
259
+ end
260
+
261
+ it "should delimit a single condition" do
262
+ qc.equal :account_id, 68
263
+ qc.fill_delimiter delimiter
264
+ params = delimiter.build_strategy_params
265
+ expect(params).to eq account: [68]
266
+ end
267
+
268
+ it "should delimit by multiple conditions (part 1)" do
269
+ qc.equal :account_id, [68, 31]
270
+ qc.fill_delimiter delimiter
271
+ params = delimiter.build_strategy_params
272
+ expect(params).to eq account: [68, 31]
273
+ end
274
+
275
+ it "should delimit a multiple conditions (part 2)" do
276
+ qc.equal :account_id, 68
277
+ qc.equal :account_id, 31
278
+ qc.fill_delimiter delimiter
279
+ params = delimiter.build_strategy_params
280
+ expect(params).to eq account: [68, 31]
281
+ end
282
+
283
+ it "should delimit by nested conditions" do
284
+ qc.equal :account_id, 68
285
+ qc.bool do
286
+ equal :account_id, 31
287
+ end
288
+ qc.fill_delimiter delimiter
289
+ params = delimiter.build_strategy_params
290
+ expect(params).to eq account: [68, 31]
291
+ end
292
+
293
+ it "should delimit only by the 'must' part of nested conditions" do
294
+ qc.equal :account_id, 68
295
+ qc.bool do
296
+ must{ equal :account_id, 31 }
297
+ must_not{ equal :account_id, 85 }
298
+ should{ equal :account_id, 58 }
299
+ end
300
+ qc.fill_delimiter delimiter
301
+ params = delimiter.build_strategy_params
302
+ expect(params).to eq account: [68, 31]
303
+ end
304
+
305
+ end
306
+
254
307
  end
255
308
  end
data/spec/query_spec.rb CHANGED
@@ -67,16 +67,6 @@ module Elasticated
67
67
 
68
68
  describe "the build method (over other fields)" do
69
69
 
70
- it "should build a 'match_all' query sorted by a custom hash" do
71
- my_custom_hash = { any_key: 'any_value' }
72
- q.custom_sort(my_custom_hash)
73
- expected_result = {
74
- query: { match_all: {} },
75
- sort: [my_custom_hash]
76
- }
77
- expect(q.build).to eq expected_result
78
- end
79
-
80
70
  it "should build a 'match_all' query sorted by a single field" do
81
71
  q.sort :field
82
72
  expected_result = {
@@ -104,16 +94,6 @@ module Elasticated
104
94
  expect(q.build).to eq expected_result
105
95
  end
106
96
 
107
- it "should build a 'match_all' query sorted by a custom script" do
108
- my_script_hash = { script: "my_script", type: "my_type" }
109
- q.sort_by_script(my_script_hash)
110
- expected_result = {
111
- query: { match_all: {} },
112
- sort: [ { _script: my_script_hash } ]
113
- }
114
- expect(q.build).to eq expected_result
115
- end
116
-
117
97
  it "should build a 'match_all' query sorted randomly" do
118
98
  q.sort_randomly
119
99
  expected_result = {
@@ -168,6 +148,15 @@ module Elasticated
168
148
  expect(q.build).to eq expected_result
169
149
  end
170
150
 
151
+ it "should build a 'match_all' query returning no source" do
152
+ q.source false
153
+ expected_result = {
154
+ query: { match_all: {} },
155
+ _source: false
156
+ }
157
+ expect(q.build).to eq expected_result
158
+ end
159
+
171
160
  it "should build an aggregated search query" do
172
161
  q.aggregations{ group :field, size: 5 }
173
162
  expect(q.build).to eq query: { match_all: {} },
@@ -191,7 +180,7 @@ module Elasticated
191
180
 
192
181
  it "should raise trying to build a non-aggregated query as an aggregated one" do
193
182
  q.size(10).sort(:field).source(:field)
194
- expect{ q.build_for_aggregations }.to raise_error
183
+ expect{ q.build_for_aggregations }.to raise_error RuntimeError
195
184
  end
196
185
 
197
186
  it "should build a 'top hits' query" do
@@ -208,12 +197,14 @@ module Elasticated
208
197
  it "should build a complex query" do
209
198
  q.filter do
210
199
  equal :last_name, 'Fernandez'
200
+ equal :age, [23, 24]
211
201
  should do
212
202
  equal :first_name, 'Pablo'
213
203
  bool do
214
204
  must do
215
205
  equal :first_name, 'Tomas'
216
206
  equal :second_name, 'Agustin'
207
+ range :age, '2001-01-01', now
217
208
  end
218
209
  end
219
210
  end
@@ -223,8 +214,8 @@ module Elasticated
223
214
  not_equal :city, 'CABA'
224
215
  end
225
216
  q.aggregations do
226
- group :entry_type, size: 5 do
227
- group :entry_name, compact: true
217
+ terms :entry_type, size: 5 do
218
+ terms :entry_name, compact: true
228
219
  end
229
220
  end
230
221
  q.size 20
@@ -239,15 +230,17 @@ module Elasticated
239
230
  filter: {
240
231
  bool: {
241
232
  must: [
242
- { terms: { last_name: ['Fernandez'] } }
233
+ { term: { last_name: 'Fernandez' } },
234
+ { terms: { age: [23, 24] } }
243
235
  ],
244
236
  should: [
245
- { terms: { first_name: ['Pablo'] } },
237
+ { term: { first_name: 'Pablo' } },
246
238
  {
247
239
  bool: {
248
240
  must: [
249
- { terms: { first_name: ['Tomas'] } },
250
- { terms: { second_name: ['Agustin'] } }
241
+ { term: { first_name: 'Tomas' } },
242
+ { term: { second_name: 'Agustin' } },
243
+ { range: { age: { gte: '2001-01-01', lte: 'now' } } }
251
244
  ]
252
245
  }
253
246
  }
@@ -258,7 +251,7 @@ module Elasticated
258
251
  query: {
259
252
  bool: {
260
253
  must_not: [
261
- { terms: { city: ['CABA'] } }
254
+ { term: { city: 'CABA' } }
262
255
  ]
263
256
  }
264
257
  }
@@ -0,0 +1,245 @@
1
+ require_relative 'spec_helper'
2
+
3
+ module Elasticated
4
+ describe Repository do
5
+
6
+ let(:transport){ double }
7
+ let(:repository){ Repository.new }
8
+ let(:query){ Query.new }
9
+
10
+ before :each do
11
+ allow(repository.client).to receive(:transport).and_return transport
12
+ end
13
+
14
+ def expect_source_preparation
15
+ expect(repository).to receive(:prepare_source).once.and_call_original
16
+ end
17
+
18
+ def expect_document_preparation
19
+ expect_source_preparation
20
+ expect(repository).to receive(:params_for_document).twice.and_call_original
21
+ end
22
+
23
+ def expect_query_preparation
24
+ expect(repository).to receive(:params_for_query).once.and_call_original
25
+ end
26
+
27
+ def expect_percolator_preparation
28
+ expect(repository).to receive(:params_for_percolator).once.and_call_original
29
+ end
30
+
31
+ def expect_ids_preparation
32
+ expect(repository).to receive(:params_for_ids).once.and_call_original
33
+ end
34
+
35
+ def expect_served_document_preparation(times=nil)
36
+ times ||= :once
37
+ expect(repository).to receive(:restore_source).send(times).and_call_original
38
+ end
39
+
40
+ context "on a query" do
41
+
42
+ it "should return the only page of results" do
43
+ response = open_response 'elasticsearch_response_1'
44
+ expect(transport).to receive(:search).with(body: query.build_for_search).and_return response
45
+ expect_query_preparation
46
+ results = repository.execute_search query, as: :single_page
47
+ expect(results.count).to eq 1
48
+ end
49
+
50
+ it "should delete all matching documents" do
51
+ expect(transport).to receive(:delete_by_query).with(body: query.build_for_count)
52
+ expect_query_preparation
53
+ repository.delete_by query
54
+ end
55
+
56
+ it "should return the qty of matching documents" do
57
+ response = open_response 'elasticsearch_count_1'
58
+ expect(transport).to receive(:count).with(body: query.build_for_count).and_return response
59
+ result = repository.execute_count query
60
+ expect(result).to eq 15
61
+ end
62
+
63
+ it "should return true on a 'exists?' query with hits > 0" do
64
+ response = open_response 'elasticsearch_count_1'
65
+ expect(transport).to receive(:count).with(body: query.build_for_count).and_return response
66
+ result = repository.exists? query
67
+ expect(result).to eq true
68
+ end
69
+
70
+ it "should return false on a 'exists?' query with hits = 0" do
71
+ response = open_response 'elasticsearch_count_2'
72
+ expect(transport).to receive(:count).with(body: query.build_for_count).and_return response
73
+ result = repository.exists? query
74
+ expect(result).to eq false
75
+ end
76
+
77
+ end
78
+
79
+ context "on an indexation" do
80
+
81
+ before :each do
82
+ expect_document_preparation
83
+ end
84
+
85
+ let(:source){ { 'name' => 'Pablo' } }
86
+ let(:document){ Document.create id: 'my_id', type: 'my_type', index: 'my_index', source: source }
87
+
88
+ it "should index the given document" do
89
+ expect(transport).to receive(:index).with(id: 'my_id', type: 'my_type', index: 'my_index', body: source)
90
+ repository.index_document document
91
+ end
92
+
93
+ end
94
+
95
+ context "on an update" do
96
+
97
+ before :each do
98
+ expect_source_preparation
99
+ end
100
+
101
+ let(:source){ { 'my_field' => 'my_value' } }
102
+
103
+ it "should update the given document" do
104
+ expect(transport).to receive(:update).with(id: 'my_id', type: 'my_type', index: 'my_index', body: { doc: source })
105
+ repository.update_document 'my_id', type: 'my_type', index: 'my_index', source: source
106
+ end
107
+
108
+ end
109
+
110
+ context "on a single document action" do
111
+
112
+ before :each do
113
+ expect_ids_preparation
114
+ end
115
+
116
+ it "should get some document by id" do
117
+ response = open_response 'elasticsearch_get_response_1'
118
+ expect(transport).to receive(:get).with(id: 'my_doc_id').and_return response
119
+ expect_served_document_preparation
120
+ result = repository.get_document 'my_doc_id'
121
+ expect(result).to be_a Document
122
+ end
123
+
124
+ it "should get some document by id and return nil if isnt present" do
125
+ response = open_response 'elasticsearch_get_response_2'
126
+ expect(transport).to receive(:get).with(id: 'my_doc_id').and_return response
127
+ result = repository.get_document 'my_doc_id'
128
+ expect(result).to be_nil
129
+ end
130
+
131
+ it "should delete some document by id" do
132
+ expect(transport).to receive(:delete).with(id: 'my_doc_id')
133
+ repository.delete_document 'my_doc_id'
134
+ end
135
+
136
+ it "should get multiple documents by id" do
137
+ response = open_response 'elasticsearch_mget_response_1'
138
+ expect(transport).to receive(:mget).with(body: { ids: ['id1', 'id2'] }).and_return response
139
+ expect_served_document_preparation :twice
140
+ result = repository.get_document ['id1', 'id2']
141
+ expect(result.count).to eq 2
142
+ expect(result[0]).to be_a Document
143
+ expect(result[1]).to be_a Document
144
+ end
145
+
146
+ end
147
+
148
+ context "on a percolation" do
149
+
150
+ before :each do
151
+ expect_percolator_preparation
152
+ end
153
+
154
+ it "should create a percolator" do
155
+ expect(transport).to receive(:index).with(index: 'my_index', type: '.percolator', id: 'my_id', body: { query: query.build_for_count })
156
+ expect_query_preparation
157
+ repository.create_percolator query, index: 'my_index', id: 'my_id'
158
+ end
159
+
160
+ it "should check a percolator" do
161
+ document = Document.new user: 'Pablo'
162
+ expect(transport).to receive(:percolate).with(index: 'my_index', type: 'my_type', body: { doc: { user: 'Pablo' } })
163
+ expect_document_preparation
164
+ repository.percolate_document document, index: 'my_index', type: 'my_type'
165
+ end
166
+
167
+ end
168
+
169
+ context "on a bulk request" do
170
+
171
+ let :source do
172
+ { some_field: 'some_value' }
173
+ end
174
+
175
+ let :document do
176
+ Document.create do |doc|
177
+ doc.id = 2
178
+ doc.type = 'post'
179
+ doc.index = 'insights'
180
+ doc.source = source
181
+ end
182
+ end
183
+
184
+ let :bulk_request do
185
+ repository.prepare_bulk do |br|
186
+ br.delete_document 2, type: 'post', index: 'insights'
187
+ br.create_document document
188
+ br.update_document 2, type: 'post', index: 'insights', source: source
189
+ br.index_document document
190
+ end
191
+ end
192
+
193
+ it "should execute the correct json" do
194
+ expect(transport).to receive(:bulk).with body: [
195
+ { delete: { _index: 'insights', _type: 'post', _id: 2 } },
196
+ { create: { _index: 'insights', _type: 'post', _id: 2 } },
197
+ { some_field: 'some_value' },
198
+ { update: { _index: 'insights', _type: 'post', _id: 2 } },
199
+ { doc: { some_field: 'some_value' } },
200
+ { index: { _index: 'insights', _type: 'post', _id: 2 } },
201
+ { some_field: 'some_value' }
202
+ ]
203
+ expect(bulk_request).to receive(:parse)
204
+ repository.execute_bulk bulk_request
205
+ end
206
+
207
+ it "should forward the 'parse' responsability" do
208
+ response = open_response 'elasticsearch_bulk_response_1'
209
+ expect(transport).to receive(:bulk).and_return response
210
+ expect(bulk_request).to receive(:parse).with(response)
211
+ repository.execute_bulk bulk_request
212
+ end
213
+
214
+ end
215
+
216
+ context "on invalid actions" do
217
+
218
+ it "should raise on an empty get" do
219
+ expect{ repository.get_document [] }.to raise_error RuntimeError
220
+ end
221
+
222
+ it "should raise on an multiple delete" do
223
+ expect{ repository.delete_document ['id1', 'id2'] }.to raise_error RuntimeError
224
+ end
225
+
226
+ it "should raise if no document source is specified" do
227
+ expect{ repository.update_document 'my_id', type: 'my_type', index: 'my_index' }.to raise_error RuntimeError
228
+ end
229
+
230
+ it "should raise if no index is specified" do
231
+ expect{ repository.update_document 'my_id', type: 'my_type', source: Hash.new }.to raise_error RuntimeError
232
+ end
233
+
234
+ it "should raise if no type is specified" do
235
+ expect{ repository.update_document 'my_id', index: 'my_index', source: Hash.new }.to raise_error RuntimeError
236
+ end
237
+
238
+ it "should raise if no document id is specified" do
239
+ expect{ repository.update_document type: 'my_type', index: 'my_index', source: Hash.new }.to raise_error RuntimeError
240
+ end
241
+
242
+ end
243
+
244
+ end
245
+ end