elasticated 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/Gemfile +4 -0
  4. data/README.md +3 -0
  5. data/Rakefile +6 -0
  6. data/elasticated.gemspec +29 -0
  7. data/lib/elasticated.rb +102 -0
  8. data/lib/elasticated/aggregation.rb +36 -0
  9. data/lib/elasticated/aggregations/cardinality_aggregation.rb +15 -0
  10. data/lib/elasticated/aggregations/count_aggregation.rb +15 -0
  11. data/lib/elasticated/aggregations/count_distinct_aggregation.rb +15 -0
  12. data/lib/elasticated/aggregations/count_filtered_aggregation.rb +29 -0
  13. data/lib/elasticated/aggregations/custom_aggregation.rb +25 -0
  14. data/lib/elasticated/aggregations/date_histogram_aggregation.rb +35 -0
  15. data/lib/elasticated/aggregations/filter_aggregation.rb +33 -0
  16. data/lib/elasticated/aggregations/filter_aggregation_evaluator.rb +22 -0
  17. data/lib/elasticated/aggregations/group_aggregation.rb +29 -0
  18. data/lib/elasticated/aggregations/histogram_aggregation.rb +34 -0
  19. data/lib/elasticated/aggregations/nested_aggregation.rb +30 -0
  20. data/lib/elasticated/aggregations/range_aggregation.rb +35 -0
  21. data/lib/elasticated/aggregations/range_aggregation_evaluator.rb +22 -0
  22. data/lib/elasticated/aggregations/ranges_builder.rb +35 -0
  23. data/lib/elasticated/aggregations/single_value_aggregation.rb +47 -0
  24. data/lib/elasticated/aggregations/subaggregated.rb +27 -0
  25. data/lib/elasticated/aggregations/sum_distinct_aggregation.rb +20 -0
  26. data/lib/elasticated/aggregations/terms_aggregation.rb +63 -0
  27. data/lib/elasticated/aggregations/top_hits_aggregation.rb +25 -0
  28. data/lib/elasticated/block_evaluation.rb +15 -0
  29. data/lib/elasticated/boolean_clause.rb +43 -0
  30. data/lib/elasticated/client.rb +84 -0
  31. data/lib/elasticated/clonable.rb +58 -0
  32. data/lib/elasticated/conditions/custom_condition.rb +19 -0
  33. data/lib/elasticated/conditions/exists_condition.rb +11 -0
  34. data/lib/elasticated/conditions/missing_condition.rb +11 -0
  35. data/lib/elasticated/conditions/nested_condition.rb +19 -0
  36. data/lib/elasticated/conditions/range_condition.rb +27 -0
  37. data/lib/elasticated/conditions/script_condition.rb +22 -0
  38. data/lib/elasticated/conditions/standard_condition.rb +26 -0
  39. data/lib/elasticated/conditions/terms_condition.rb +22 -0
  40. data/lib/elasticated/conditions/wildcard_condition.rb +18 -0
  41. data/lib/elasticated/conditions_builder.rb +75 -0
  42. data/lib/elasticated/configurable.rb +9 -0
  43. data/lib/elasticated/configuration.rb +9 -0
  44. data/lib/elasticated/default_logger.rb +27 -0
  45. data/lib/elasticated/delimiters/date_field_delimiter.rb +33 -0
  46. data/lib/elasticated/delimiters/standard_field_delimiter.rb +33 -0
  47. data/lib/elasticated/delimiters/term_field_delimiter.rb +24 -0
  48. data/lib/elasticated/document.rb +46 -0
  49. data/lib/elasticated/helpers.rb +28 -0
  50. data/lib/elasticated/index_selector.rb +44 -0
  51. data/lib/elasticated/inspectionable.rb +9 -0
  52. data/lib/elasticated/mapping.rb +19 -0
  53. data/lib/elasticated/mapping/builder.rb +36 -0
  54. data/lib/elasticated/mapping/fields_builder.rb +148 -0
  55. data/lib/elasticated/mapping/nested_builder.rb +15 -0
  56. data/lib/elasticated/mapping/object_builder.rb +15 -0
  57. data/lib/elasticated/mapping/partial.rb +11 -0
  58. data/lib/elasticated/mapping/type_builder.rb +14 -0
  59. data/lib/elasticated/partitioned_repository.rb +27 -0
  60. data/lib/elasticated/query.rb +159 -0
  61. data/lib/elasticated/query_aggregations.rb +71 -0
  62. data/lib/elasticated/query_conditions.rb +89 -0
  63. data/lib/elasticated/repositories/monthly_partitioned_repository.rb +96 -0
  64. data/lib/elasticated/repository.rb +139 -0
  65. data/lib/elasticated/results.rb +43 -0
  66. data/lib/version.rb +92 -0
  67. data/spec/aggregation_spec.rb +587 -0
  68. data/spec/date_field_delimiter_spec.rb +67 -0
  69. data/spec/document_spec.rb +44 -0
  70. data/spec/elasticsearch_hit_1.json +14 -0
  71. data/spec/elasticsearch_response_1.json +29 -0
  72. data/spec/elasticsearch_response_2.json +44 -0
  73. data/spec/elasticsearch_top_hits_response.json +20 -0
  74. data/spec/integration_spec.rb +184 -0
  75. data/spec/mapping_spec.rb +219 -0
  76. data/spec/monthly_partitioned_repository_spec.rb +99 -0
  77. data/spec/query_aggregations_spec.rb +44 -0
  78. data/spec/query_conditions_spec.rb +314 -0
  79. data/spec/query_spec.rb +265 -0
  80. data/spec/results_spec.rb +69 -0
  81. data/spec/spec_helper.rb +2 -0
  82. data/spec/term_field_delimiter_spec.rb +39 -0
  83. metadata +225 -0
@@ -0,0 +1,99 @@
1
+ require_relative 'spec_helper'
2
+
3
+ module Elasticated
4
+ describe MonthlyPartitionedRepository do
5
+
6
+ let :repository do
7
+ MonthlyPartitionedRepository.new index_name: 'fbinsights-v3', index_alias: 'fbinsights'
8
+ end
9
+
10
+ before :each do
11
+ Elasticated.configure do |config|
12
+ config.logger = double.as_null_object
13
+ end
14
+ end
15
+
16
+ it "should return the correct index name" do
17
+ date = Date.parse '2015-09-04'
18
+ name = repository.index_name_for date
19
+ expect(name).to eq 'fbinsights-v3-2015-09'
20
+ end
21
+
22
+ it "should return the correct index alias" do
23
+ date = Date.parse '2015-09-04'
24
+ name = repository.index_alias_for date
25
+ expect(name).to eq 'fbinsights-2015-09'
26
+ end
27
+
28
+ context "on a search" do
29
+
30
+ let :query do
31
+ Query.new # TODO date
32
+ end
33
+
34
+ it "should execute a search on the correct index" do
35
+ expect(repository).to receive(:_exec_search).with query, index: 'fbinsights' # TODO
36
+ repository.execute_search query
37
+ end
38
+
39
+ it "should execute a count on the correct index" do
40
+ expect(repository).to receive(:_exec_count).with query, index: 'fbinsights' # TODO
41
+ repository.execute_count query
42
+ end
43
+
44
+ it "should execute a delete on the correct index" do
45
+ expect(repository).to receive(:_exec_delete).with query, index: 'fbinsights' # TODO
46
+ repository.delete_by query
47
+ end
48
+
49
+ end
50
+
51
+ context "on an indexation" do
52
+
53
+ let :document do
54
+ Document.create source: { 'date' => '2015-09-04' }
55
+ end
56
+
57
+ it "should use the appropiated index alias" do
58
+ client = repository.client
59
+ expect(client).to receive(:index_exists?).with('fbinsights-2015-09').and_return true
60
+ expect(client).to receive(:index_document).with document.source, index: 'fbinsights-2015-09', type: 'post'
61
+ repository.index_document document, type: 'post'
62
+ end
63
+
64
+ it "should create the appropiated index (only if dynamic creation is enabled)" do
65
+ client = repository.client
66
+ expect(client).to receive(:index_exists?).with('fbinsights-2015-09').and_return false
67
+ expect{ repository.index_document document, type: 'post' }.to raise_error
68
+ expect(client).to receive(:index_exists?).with('fbinsights-2015-09').and_return false
69
+ expect(client).to receive(:create_index).with 'fbinsights-v3-2015-09', anything
70
+ repository.dynamic_creation = true
71
+ expect(client).to receive(:create_alias).with('fbinsights-v3-2015-09', 'fbinsights-2015-09').once
72
+ expect(client).to receive(:create_alias).with('fbinsights-v3-2015-09', 'fbinsights').once
73
+ expect(client).to receive(:index_document).with document.source, index: 'fbinsights-2015-09', type: 'post'
74
+ repository.index_document document, type: 'post'
75
+ end
76
+
77
+ end
78
+
79
+ context "the index creation method" do
80
+
81
+ let :date do
82
+ Date.parse '2015-09-04'
83
+ end
84
+
85
+ it "creates the appropiated index" do
86
+ expect(repository.client).to receive(:create_index).with 'fbinsights-v3-2015-09', anything
87
+ repository.create_index! date
88
+ end
89
+
90
+ it "creates the appropiated alias" do
91
+ expect(repository.client).to receive(:create_alias).with('fbinsights-v3-2015-09', 'fbinsights-2015-09').once
92
+ expect(repository.client).to receive(:create_alias).with('fbinsights-v3-2015-09', 'fbinsights').once
93
+ repository.create_alias! date
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+ end
@@ -0,0 +1,44 @@
1
+ require_relative 'spec_helper'
2
+
3
+ module Elasticated
4
+ describe QueryAggregations do
5
+
6
+ let(:qa){ QueryAggregations.new }
7
+
8
+ describe "the aggragation lookup method" do
9
+
10
+ class DummieAggregation
11
+ def build; { dummie_body: {} }; end
12
+ def name; :nn; end
13
+ end
14
+
15
+ it "should instantiate the correct class" do
16
+ qa.dummie
17
+ expected_result = { nn: { dummie_body: {} } }
18
+ expect(qa.build).to eq expected_result
19
+ end
20
+
21
+ end
22
+
23
+ describe "the build method" do
24
+
25
+ it "should build a single aggregated body" do
26
+ qa.sum :numeric
27
+ expected_result = { sum_numeric: { sum: { field: :numeric } } }
28
+ expect(qa.build).to eq expected_result
29
+ end
30
+
31
+ it "should build a multiple aggregated body" do
32
+ qa.sum :numeric
33
+ qa.max :numeric
34
+ expected_result = {
35
+ sum_numeric: { sum: { field: :numeric } },
36
+ max_numeric: { max: { field: :numeric } }
37
+ }
38
+ expect(qa.build).to eq expected_result
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,314 @@
1
+ require_relative 'spec_helper'
2
+
3
+ module Elasticated
4
+ describe QueryConditions do
5
+
6
+ let(:qc){ QueryConditions.new }
7
+
8
+ describe 'the build method' do
9
+
10
+ it "should build a 'match_all' condition" do
11
+ expected_result = { match_all: {} }
12
+ expect(qc.build).to eq expected_result
13
+ end
14
+
15
+ it "should build a 'terms' condition" do
16
+ qc.equal :field, :value
17
+ expected_result = { terms: { field: [:value] } }
18
+ expect(qc.build).to eq expected_result
19
+ end
20
+
21
+ 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 } }
24
+ expect(qc.build).to eq expected_result
25
+ end
26
+
27
+ it "should build a 'must_not>terms' condition" do
28
+ qc.not_equal :field, :value
29
+ expected_result = { bool: { must_not: [ { terms: { field: [:value] } } ] } }
30
+ expect(qc.build).to eq expected_result
31
+ end
32
+
33
+ it "should build a 'with' condition" do
34
+ qc.with :field
35
+ expected_result = { wildcard: { field: '*' } }
36
+ expect(qc.build).to eq expected_result
37
+ end
38
+
39
+ it "should build a 'without' condition" do
40
+ qc.without :field
41
+ expected_result = { bool: { must_not: [ { wildcard: { field: '*' } } ] } }
42
+ expect(qc.build).to eq expected_result
43
+ end
44
+
45
+ it "should build a 'wildcard' condition" do
46
+ qc.wildcard :field, 'regex'
47
+ expected_result = { wildcard: { field: 'regex' } }
48
+ expect(qc.build).to eq expected_result
49
+ end
50
+
51
+ it "should build an 'exists' condition" do
52
+ qc.exists :field_name
53
+ expected_result = { exists: { field: :field_name } }
54
+ expect(qc.build).to eq expected_result
55
+ end
56
+
57
+ it "should build a 'missing' condition" do
58
+ qc.missing :field_name
59
+ expected_result = { missing: { field: :field_name } }
60
+ expect(qc.build).to eq expected_result
61
+ end
62
+
63
+ it "should build a 'between' condition" do
64
+ qc.between :field, :min_value, :max_value
65
+ expected_result = { range: { field: { gte: :min_value, lte: :max_value } } }
66
+ expect(qc.build).to eq expected_result
67
+ end
68
+
69
+ it "should build a 'greater_than' condition" do
70
+ qc.greater_than :field, :min_value
71
+ expected_result = { range: { field: { gt: :min_value } } }
72
+ expect(qc.build).to eq expected_result
73
+ end
74
+
75
+ it "should build a 'less_than' condition" do
76
+ qc.less_than :field, :max_value
77
+ expected_result = { range: { field: { lt: :max_value } } }
78
+ expect(qc.build).to eq expected_result
79
+ end
80
+
81
+ it "should build a 'greater_equal' condition" do
82
+ qc.greater_equal :field, :min_value
83
+ expected_result = { range: { field: { gte: :min_value } } }
84
+ expect(qc.build).to eq expected_result
85
+ end
86
+
87
+ it "should build a 'less_equal' condition" do
88
+ qc.less_equal :field, :max_value
89
+ expected_result = { range: { field: { lte: :max_value } } }
90
+ expect(qc.build).to eq expected_result
91
+ end
92
+
93
+ it "should build a 'between' condition (with params)" do
94
+ qc.between :field, :min_value, :max_value, execution: :index, _cache: true
95
+ expected_result = { range: { execution: :index, _cache: true, field: { gte: :min_value, lte: :max_value } } }
96
+ expect(qc.build).to eq expected_result
97
+ end
98
+
99
+ it "should build a 'script' condition" do
100
+ qc.script 'your_script_here'
101
+ expected_result = { script: { script: 'your_script_here' } }
102
+ expect(qc.build).to eq expected_result
103
+ end
104
+
105
+ it "should build a 'script' condition (with params)" do
106
+ qc.script 'your_script_here', first_param: :one
107
+ expected_result = { script: { script: 'your_script_here', params: { first_param: :one } } }
108
+ expect(qc.build).to eq expected_result
109
+ end
110
+
111
+ it "should build a custom 'must' condition" do
112
+ qc.must{ custom term: { field: :value } }
113
+ expected_result = { term: { field: :value } }
114
+ expect(qc.build).to eq expected_result
115
+ end
116
+
117
+ it "should build a custom 'must_not' condition" do
118
+ qc.must_not{ custom term: { field: :value } }
119
+ expected_result = { bool: { must_not: [ { term: { field: :value } } ] } }
120
+ expect(qc.build).to eq expected_result
121
+ end
122
+
123
+ it "should build a 'nested' condition" do
124
+ qc.nested :hash do |n|
125
+ n.equal :field, :value
126
+ end
127
+ expected_result = { nested: { path: :hash, filter: { terms: { field: [:value] } } } }
128
+ expect(qc.build).to eq expected_result
129
+ end
130
+
131
+ it "should build a 'nested' condition (with params)" do
132
+ qc.nested :hash, _cache: true do |n|
133
+ n.equal :field, :value
134
+ end
135
+ expected_result = { nested: { path: :hash, _cache: true, filter: { terms: { field: [:value] } } } }
136
+ expect(qc.build).to eq expected_result
137
+ end
138
+
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
+ it "should build a 'bool>must' condition" do
158
+ qc.exists :field
159
+ qc.equal :field, :value
160
+ expected_result = { bool: { must: [ { exists: { field: :field } }, { terms: { field: [:value] } } ] } }
161
+ expect(qc.build).to eq expected_result
162
+ end
163
+
164
+ it "should build a 'bool>must' cached condition" do
165
+ qc.exists :field
166
+ qc.equal :field, :value
167
+ qc.cache
168
+ expected_result = { bool: { must: [ { exists: { field: :field } }, { terms: { field: [:value] } } ], _cache: true } }
169
+ expect(qc.build).to eq expected_result
170
+ end
171
+
172
+ it "should build a 'bool>must+must_not+should' condition" do
173
+ qc.equal :field_one, :value_one
174
+ qc.not_equal :field_two, :value_two
175
+ qc.should{ equal :field_three, :value_three }
176
+ qc.minimum_should_match 2
177
+ 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] } } ],
181
+ minimum_should_match: 2
182
+ } }
183
+ expect(qc.build).to eq expected_result
184
+ end
185
+
186
+ it "should build nested bool conditions" do
187
+ qc.must{ equal :age, 19 }
188
+ qc.should{ equal :name, 'Pablo' }
189
+ qc.should{ equal :name, 'Santiago' }
190
+ expected_result = {
191
+ bool: {
192
+ must: [
193
+ { terms: { age: [19] } }
194
+ ],
195
+ should: [
196
+ { terms: { name: ['Pablo'] } },
197
+ { terms: { name: ['Santiago'] } }
198
+ ]
199
+ }
200
+ }
201
+ expect(qc.build).to eq expected_result
202
+ end
203
+
204
+ it "should build nested bools" do
205
+ qc.should do
206
+ equal :first_name, 'Pablo'
207
+ equal :last_name, 'Fernandez'
208
+ bool do
209
+ equal :age, 24
210
+ equal :country, 'Argentina'
211
+ end
212
+ end
213
+ expected_result = {
214
+ bool: {
215
+ should: [
216
+ { terms: { first_name: ['Pablo'] } },
217
+ { terms: { last_name: ['Fernandez'] } },
218
+ {
219
+ bool: {
220
+ must: [
221
+ { terms: { age: [24] } },
222
+ { terms: { country: ['Argentina'] } }
223
+ ]
224
+ }
225
+ }
226
+ ]
227
+ }
228
+ }
229
+ expect(qc.build).to eq expected_result
230
+ end
231
+
232
+ end
233
+
234
+ describe "the clone method" do
235
+
236
+ it 'should clone the must and must_not collections' do
237
+ qc.equal :field_one, :value_one
238
+ qc.not_equal :field_two, :value_two
239
+ qc.should{ equal :field_three, :value_three }
240
+ new_qc = qc.clone
241
+ qc.equal :field_four, :value_four
242
+ qc.not_equal :field_five, :value_five
243
+ qc.should{ equal :field_six, :value_six }
244
+ 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] } } ]
248
+ } }
249
+ expect(new_qc.build).to eq expected_result
250
+ end
251
+
252
+ end
253
+
254
+ describe "the term delimiter" do
255
+
256
+ let :delimiter do
257
+ Delimiters::TermFieldDelimiter.new field: :account_id, as: :account
258
+ end
259
+
260
+ it "should not delimit anything" do
261
+ qc.equal :other_field, 68
262
+ qc.fill_delimiter delimiter
263
+ params = delimiter.build_strategy_params
264
+ expect(params).to be_empty
265
+ end
266
+
267
+ it "should delimit a single condition" do
268
+ qc.equal :account_id, 68
269
+ qc.fill_delimiter delimiter
270
+ params = delimiter.build_strategy_params
271
+ expect(params).to eq account: [68]
272
+ end
273
+
274
+ it "should delimit by multiple conditions (part 1)" do
275
+ qc.equal :account_id, [68, 31]
276
+ qc.fill_delimiter delimiter
277
+ params = delimiter.build_strategy_params
278
+ expect(params).to eq account: [68, 31]
279
+ end
280
+
281
+ it "should delimit a multiple conditions (part 2)" do
282
+ qc.equal :account_id, 68
283
+ qc.equal :account_id, 31
284
+ qc.fill_delimiter delimiter
285
+ params = delimiter.build_strategy_params
286
+ expect(params).to eq account: [68, 31]
287
+ end
288
+
289
+ it "should delimit by nested conditions" do
290
+ qc.equal :account_id, 68
291
+ qc.bool do
292
+ equal :account_id, 31
293
+ end
294
+ qc.fill_delimiter delimiter
295
+ params = delimiter.build_strategy_params
296
+ expect(params).to eq account: [68, 31]
297
+ end
298
+
299
+ it "should delimit only by the 'must' part of nested conditions" do
300
+ qc.equal :account_id, 68
301
+ qc.bool do
302
+ must{ equal :account_id, 31 }
303
+ must_not{ equal :account_id, 85 }
304
+ should{ equal :account_id, 58 }
305
+ end
306
+ qc.fill_delimiter delimiter
307
+ params = delimiter.build_strategy_params
308
+ expect(params).to eq account: [68, 31]
309
+ end
310
+
311
+ end
312
+
313
+ end
314
+ end