elasticated 1.0.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.
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