elasticated 2.5.5 → 3.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.
- checksums.yaml +4 -4
- data/README.md +35 -2
- data/Rakefile +52 -1
- data/elasticated.gemspec +3 -1
- data/lib/elasticated.rb +20 -24
- data/lib/elasticated/aggregation.rb +3 -6
- data/lib/elasticated/aggregations/date_histogram_aggregation.rb +6 -1
- data/lib/elasticated/aggregations/filter_aggregation.rb +8 -12
- data/lib/elasticated/aggregations/filter_aggregation_evaluator.rb +1 -1
- data/lib/elasticated/aggregations/group_aggregation.rb +14 -11
- data/lib/elasticated/aggregations/range_aggregation.rb +10 -11
- data/lib/elasticated/aggregations/range_aggregation_evaluator.rb +1 -1
- data/lib/elasticated/aggregations/ranges_builder.rb +2 -2
- data/lib/elasticated/aggregations/safe_date_histogram_aggregation.rb +7 -2
- data/lib/elasticated/aggregations/subaggregated.rb +1 -1
- data/lib/elasticated/boolean_clause.rb +4 -3
- data/lib/elasticated/bulk_actions/create_action.rb +14 -0
- data/lib/elasticated/bulk_actions/delete_action.rb +30 -0
- data/lib/elasticated/bulk_actions/index_action.rb +35 -0
- data/lib/elasticated/bulk_actions/standard_action.rb +22 -0
- data/lib/elasticated/bulk_actions/update_action.rb +44 -0
- data/lib/elasticated/bulk_actions/upsert_action.rb +14 -0
- data/lib/elasticated/bulk_request.rb +58 -0
- data/lib/elasticated/bulk_request/response.rb +32 -0
- data/lib/elasticated/bulk_request/response_item.rb +39 -0
- data/lib/elasticated/client.rb +27 -3
- data/lib/elasticated/conditions/custom_condition.rb +3 -3
- data/lib/elasticated/conditions/range_condition.rb +5 -2
- data/lib/elasticated/conditions/script_condition.rb +3 -3
- data/lib/elasticated/conditions/standard_condition.rb +4 -5
- data/lib/elasticated/conditions/term_condition.rb +22 -0
- data/lib/elasticated/conditions/terms_condition.rb +2 -2
- data/lib/elasticated/conditions_builder.rb +19 -4
- data/lib/elasticated/delimiters/date_field_delimiter.rb +21 -12
- data/lib/elasticated/delimiters/standard_field_delimiter.rb +18 -2
- data/lib/elasticated/delimiters/term_field_delimiter.rb +6 -5
- data/lib/elasticated/document.rb +20 -1
- data/lib/elasticated/enum.rb +17 -0
- data/lib/elasticated/index_selector.rb +26 -25
- data/lib/elasticated/mapping.rb +2 -4
- data/lib/elasticated/mapping/builder.rb +3 -2
- data/lib/elasticated/mapping/fields_builder.rb +13 -9
- data/lib/elasticated/mapping/object_builder.rb +38 -4
- data/lib/elasticated/mapping/type_builder.rb +3 -5
- data/lib/elasticated/mixins/block_evaluation.rb +17 -0
- data/lib/elasticated/mixins/clonable.rb +60 -0
- data/lib/elasticated/mixins/configurable.rb +22 -0
- data/lib/elasticated/mixins/inspectionable.rb +16 -0
- data/lib/elasticated/partitioned_repository.rb +24 -18
- data/lib/elasticated/query.rb +27 -21
- data/lib/elasticated/query_aggregations.rb +5 -7
- data/lib/elasticated/query_conditions.rb +6 -3
- data/lib/elasticated/quick.rb +7 -0
- data/lib/elasticated/repository.rb +184 -40
- data/lib/elasticated/repository/intelligent_search.rb +3 -3
- data/lib/elasticated/repository/normal_search.rb +2 -2
- data/lib/elasticated/repository/resumable_search.rb +5 -5
- data/lib/elasticated/repository/scan_scroll_search.rb +4 -4
- data/lib/elasticated/repository/scroll_search.rb +3 -3
- data/lib/elasticated/repository/search.rb +7 -0
- data/lib/elasticated/repository/single_page_search.rb +1 -1
- data/lib/elasticated/results.rb +14 -0
- data/lib/version.rb +18 -25
- data/spec/aggregation_spec.rb +95 -16
- data/spec/bulk_request_spec.rb +158 -0
- data/spec/date_field_delimiter_spec.rb +50 -6
- data/spec/document_spec.rb +1 -5
- data/spec/integration_spec.rb +7 -7
- data/spec/mapping_spec.rb +128 -8
- data/spec/partitioned_repository_spec.rb +218 -0
- data/spec/query_conditions_spec.rb +98 -45
- data/spec/query_spec.rb +21 -28
- data/spec/repository_spec.rb +245 -0
- data/spec/results_spec.rb +0 -4
- data/spec/sample_responses/elasticsearch_bulk_response_1.json +35 -0
- data/spec/sample_responses/elasticsearch_bulk_response_2.json +20 -0
- data/spec/sample_responses/elasticsearch_count_1.json +8 -0
- data/spec/sample_responses/elasticsearch_count_2.json +8 -0
- data/spec/sample_responses/elasticsearch_get_response_1.json +10 -0
- data/spec/sample_responses/elasticsearch_get_response_2.json +6 -0
- data/spec/{elasticsearch_hit_1.json → sample_responses/elasticsearch_hit_1.json} +0 -0
- data/spec/sample_responses/elasticsearch_mget_response_1.json +25 -0
- data/spec/{elasticsearch_response_1.json → sample_responses/elasticsearch_response_1.json} +0 -0
- data/spec/{elasticsearch_response_2.json → sample_responses/elasticsearch_response_2.json} +0 -0
- data/spec/{elasticsearch_top_hits_response.json → sample_responses/elasticsearch_top_hits_response.json} +0 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/spec_helper/fake_index_selector.rb +27 -0
- data/spec/term_field_delimiter_spec.rb +8 -8
- metadata +80 -26
- data/lib/elasticated/block_evaluation.rb +0 -15
- data/lib/elasticated/clonable.rb +0 -58
- data/lib/elasticated/configurable.rb +0 -20
- data/lib/elasticated/date_delimiter_factory.rb +0 -123
- data/lib/elasticated/delimiter_visitor.rb +0 -53
- data/lib/elasticated/inspectionable.rb +0 -9
- data/lib/elasticated/strategy_params_for_query_service.rb +0 -14
- data/lib/elasticated/term_delimiter_factory.rb +0 -73
- data/spec/delimiter_factory_spec.rb +0 -399
- data/spec/strategy_params_for_query_service_spec.rb +0 -387
@@ -1,7 +1,7 @@
|
|
1
1
|
module Elasticated
|
2
2
|
class Repository
|
3
3
|
class IntelligentSearch < Search
|
4
|
-
include Configurable
|
4
|
+
include Mixins::Configurable
|
5
5
|
|
6
6
|
# INTELLIGENT SEARCH CASES
|
7
7
|
# ------------ without sorting
|
@@ -15,14 +15,14 @@ module Elasticated
|
|
15
15
|
# without size, with offset => normal_pagination
|
16
16
|
# with size, with offset => single_page or normal_pagination
|
17
17
|
|
18
|
-
# if the query is aggregated and the search strategy is
|
18
|
+
# if the query is aggregated and the search strategy is a
|
19
19
|
# scroll-like alternative, we must do a 2-step search process
|
20
20
|
|
21
21
|
def best_search_method
|
22
22
|
if query.limited? && !query.heavy_for?(repository)
|
23
23
|
SinglePageSearch.new repository, query, aggregated, opts
|
24
24
|
else
|
25
|
-
if query.
|
25
|
+
if query.offset?
|
26
26
|
NormalSearch.new repository, query, aggregated, opts
|
27
27
|
else
|
28
28
|
if query.sorted?
|
@@ -10,7 +10,7 @@ module Elasticated
|
|
10
10
|
|
11
11
|
override! body, size, offset
|
12
12
|
response = client.search body, opts
|
13
|
-
results =
|
13
|
+
results = parse_and_prepare_results response, query
|
14
14
|
|
15
15
|
target_size = query.limited? ? query._size : (results.hits.total - offset)
|
16
16
|
total_pages = (target_size / size.to_f).ceil
|
@@ -25,7 +25,7 @@ module Elasticated
|
|
25
25
|
override! body, size, offset
|
26
26
|
|
27
27
|
response = client.search body, opts
|
28
|
-
new_results =
|
28
|
+
new_results = parse_and_prepare_results response
|
29
29
|
results.append new_results
|
30
30
|
break if new_results.count < size
|
31
31
|
|
@@ -2,8 +2,8 @@ module Elasticated
|
|
2
2
|
class Repository
|
3
3
|
class ResumableSearch < Search
|
4
4
|
|
5
|
-
def self.from_scroll_id(
|
6
|
-
search = new
|
5
|
+
def self.from_scroll_id(repository, scroll_id)
|
6
|
+
search = new repository, nil
|
7
7
|
search.scroll_id = scroll_id
|
8
8
|
search
|
9
9
|
end
|
@@ -15,12 +15,12 @@ module Elasticated
|
|
15
15
|
aggregation_results = if aggregated
|
16
16
|
body = query.build_for_aggregations
|
17
17
|
response = client.search body, opts
|
18
|
-
|
18
|
+
parse_and_prepare_results response, query
|
19
19
|
end
|
20
20
|
# search
|
21
21
|
body = query.build_for_search
|
22
22
|
response = client.search body, opts.merge(scroll: scroll_expiration_time, size: scroll_page_size)
|
23
|
-
results =
|
23
|
+
results = parse_and_prepare_results response
|
24
24
|
results.append aggregation_results if aggregation_results
|
25
25
|
self.scroll_id = results.scroll_id
|
26
26
|
mark_completed! if results.documents.count < scroll_page_size
|
@@ -31,7 +31,7 @@ module Elasticated
|
|
31
31
|
raise "No scroll_id present" unless scroll_id
|
32
32
|
raise "No more information to fetch: scroll completed" if completed?
|
33
33
|
response = client.scroll scroll_id, scroll: scroll_expiration_time
|
34
|
-
results =
|
34
|
+
results = parse_and_prepare_results response
|
35
35
|
self.scroll_id = results.scroll_id
|
36
36
|
mark_completed! if results.documents.empty?
|
37
37
|
results
|
@@ -5,7 +5,7 @@ module Elasticated
|
|
5
5
|
def fetch_aggregations
|
6
6
|
body = query.build_for_aggregations
|
7
7
|
response = client.search body, opts
|
8
|
-
|
8
|
+
parse_and_prepare_results response, query
|
9
9
|
end
|
10
10
|
|
11
11
|
def execute
|
@@ -14,17 +14,17 @@ module Elasticated
|
|
14
14
|
if aggregated
|
15
15
|
body = query.build_for_aggregations
|
16
16
|
response = client.search body, opts
|
17
|
-
results =
|
17
|
+
results = parse_and_prepare_results response, query
|
18
18
|
end
|
19
19
|
# search
|
20
20
|
body = query.build_for_search
|
21
21
|
response = client.search body, opts.merge(search_type: 'scan', scroll: scroll_expiration_time, size: scroll_page_size)
|
22
|
-
results =
|
22
|
+
results = parse_and_prepare_results response
|
23
23
|
results.append fetch_aggregations if aggregated
|
24
24
|
doc_count = 0
|
25
25
|
loop do
|
26
26
|
response = client.scroll results.scroll_id, scroll: scroll_expiration_time
|
27
|
-
new_results =
|
27
|
+
new_results = parse_and_prepare_results response
|
28
28
|
hits = new_results.documents
|
29
29
|
break if hits.empty?
|
30
30
|
if query.limited? && (doc_count + hits.count > query._size)
|
@@ -5,7 +5,7 @@ module Elasticated
|
|
5
5
|
def fetch_aggregations
|
6
6
|
body = query.build_for_aggregations
|
7
7
|
response = client.search body, opts
|
8
|
-
|
8
|
+
parse_and_prepare_results response, query
|
9
9
|
end
|
10
10
|
|
11
11
|
def execute
|
@@ -14,7 +14,7 @@ module Elasticated
|
|
14
14
|
|
15
15
|
override! body
|
16
16
|
response = client.search body, opts.merge(scroll: scroll_expiration_time, size: scroll_page_size)
|
17
|
-
results =
|
17
|
+
results = parse_and_prepare_results response, query
|
18
18
|
results.append fetch_aggregations if aggregated
|
19
19
|
|
20
20
|
target_size = query.limited? ? query._size : results.hits.total
|
@@ -26,7 +26,7 @@ module Elasticated
|
|
26
26
|
break if current_page >= total_pages
|
27
27
|
|
28
28
|
response = client.scroll results.scroll_id, scroll: scroll_expiration_time
|
29
|
-
new_results =
|
29
|
+
new_results = parse_and_prepare_results response
|
30
30
|
hits = new_results.documents
|
31
31
|
doc_count = results.documents.count
|
32
32
|
new_results.documents = hits.first(target_size - doc_count) if query.limited? && (doc_count + hits.count > target_size)
|
@@ -40,6 +40,13 @@ module Elasticated
|
|
40
40
|
repository.scroll_page_size
|
41
41
|
end
|
42
42
|
|
43
|
+
# results preparation
|
44
|
+
|
45
|
+
def parse_and_prepare_results(response, query=nil)
|
46
|
+
results = Results.parse response, query
|
47
|
+
repository.send :prepare_served_results, results # TODO fixme
|
48
|
+
end
|
49
|
+
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
data/lib/elasticated/results.rb
CHANGED
@@ -29,6 +29,8 @@ module Elasticated
|
|
29
29
|
alias_method :from_elasticsearch_response, :parse
|
30
30
|
end
|
31
31
|
|
32
|
+
include Mixins::Inspectionable
|
33
|
+
|
32
34
|
attr_accessor :scroll_id
|
33
35
|
attr_accessor :took, :timed_out
|
34
36
|
attr_accessor :shards # methods: total, successful, failed
|
@@ -58,5 +60,17 @@ module Elasticated
|
|
58
60
|
documents.count
|
59
61
|
end
|
60
62
|
|
63
|
+
def text_for_inspect
|
64
|
+
text = "#{hits.total} hits"
|
65
|
+
text = case documents.count
|
66
|
+
when 0; "#{text}, no documents"
|
67
|
+
when 1; "#{text}, 1 document"
|
68
|
+
else; "#{text}, #{documents.count} documents"
|
69
|
+
end
|
70
|
+
text = aggregations ? "#{text}, with aggregations" : "#{text}, no aggregations"
|
71
|
+
text = "#{text}, including scroll_id" if scroll_id
|
72
|
+
text
|
73
|
+
end
|
74
|
+
|
61
75
|
end
|
62
76
|
end
|
data/lib/version.rb
CHANGED
@@ -1,33 +1,26 @@
|
|
1
1
|
module Elasticated
|
2
|
-
VERSION = '
|
2
|
+
VERSION = '3.0.0'
|
3
3
|
end
|
4
4
|
|
5
5
|
# Changelog
|
6
6
|
|
7
|
-
#
|
8
|
-
# Se
|
9
|
-
|
10
|
-
#
|
11
|
-
#
|
12
|
-
|
13
|
-
#
|
14
|
-
#
|
15
|
-
|
16
|
-
#
|
17
|
-
# Se
|
18
|
-
|
19
|
-
#
|
20
|
-
#
|
21
|
-
|
22
|
-
#
|
23
|
-
# Ahora
|
24
|
-
# Se puede delimitar por aggregations
|
25
|
-
|
26
|
-
# 2.4.0
|
27
|
-
# Ahora se puede ordenar un search por un campo, script o hash custom
|
28
|
-
|
29
|
-
# 2.3.0
|
30
|
-
# Ahora DateFieldDelimiter admite multiples fechas declaradas en un TermsCondition
|
7
|
+
# Ahora Repository#execute_aggregated_search puede definir automaticamente si ejecutar las aggregations o no
|
8
|
+
# Se agrega el alias 'range' para la condicion 'between'
|
9
|
+
# Se agrega el alias 'terms' para la condicion 'equal'
|
10
|
+
# Se agregan get, delete, y mget a Repository
|
11
|
+
# Ahora el GroupAggregation se puede invocar como 'terms' ademas de 'group'
|
12
|
+
# Se elimina la opcion 'include_count' de todas las aggregations que la utilizaban
|
13
|
+
# Ya no se permite pasar la opcion 'compact' a aggregations que posean subaggregations
|
14
|
+
# Ahora se puede llamar a bloque de aggregations por medio del alias 'aggs'
|
15
|
+
# Ahora Repository#update_document actualiza parcialmente el documento
|
16
|
+
# Cambian los pre-action y post-action preparation methods
|
17
|
+
# Se incluye la extension 'test cluster' y las tareas rake para administrarlo
|
18
|
+
# ResumableSearch ahora hace 'restore' de los documentos que devuelve
|
19
|
+
# Se agregan mejores vistas de inspeccion para Query, Results y Document
|
20
|
+
# Ahora se pueden pedir los documentos sin source
|
21
|
+
# Ahora el PartitionedRepository soporta :now
|
22
|
+
# Se agrega TermCondition
|
23
|
+
# Ahora se puede especificar si el mapping es dinamico
|
31
24
|
|
32
25
|
# 2.2.0
|
33
26
|
# Se agrega la funcionalidad para especificar un orden aleatorio en las queries
|
data/spec/aggregation_spec.rb
CHANGED
@@ -147,9 +147,9 @@ module Elasticated
|
|
147
147
|
it "should map a group aggregation response" do
|
148
148
|
agg = GroupAggregation.new :field
|
149
149
|
response = { 'buckets' => [
|
150
|
-
{ 'key' => 'value1', 'doc_count' => 'count1' },
|
151
|
-
{ 'key' => 'value2', 'doc_count' => 'count2' },
|
152
|
-
{ 'key' => 'value3', 'doc_count' => 'count3' }
|
150
|
+
{ 'key' => 'value1', 'doc_count' => 'count1', 'key_as_string' => 'value1str' },
|
151
|
+
{ 'key' => 'value2', 'doc_count' => 'count2', 'key_as_string' => 'value2str' },
|
152
|
+
{ 'key' => 'value3', 'doc_count' => 'count3', 'key_as_string' => 'value3str' }
|
153
153
|
] }
|
154
154
|
expect(agg.parse(response)).to eq({
|
155
155
|
'value1' => { 'count' => 'count1' },
|
@@ -158,12 +158,26 @@ module Elasticated
|
|
158
158
|
})
|
159
159
|
end
|
160
160
|
|
161
|
+
it "should map a group aggregation response including the 'key_as_string' value" do
|
162
|
+
agg = GroupAggregation.new :field, key_as_string: true
|
163
|
+
response = { 'buckets' => [
|
164
|
+
{ 'key' => 'value1', 'doc_count' => 'count1', 'key_as_string' => 'value1str' },
|
165
|
+
{ 'key' => 'value2', 'doc_count' => 'count2', 'key_as_string' => 'value2str' },
|
166
|
+
{ 'key' => 'value3', 'doc_count' => 'count3', 'key_as_string' => 'value3str' }
|
167
|
+
] }
|
168
|
+
expect(agg.parse(response)).to eq({
|
169
|
+
'value1' => { 'count' => 'count1', 'key_as_string' => 'value1str' },
|
170
|
+
'value2' => { 'count' => 'count2', 'key_as_string' => 'value2str' },
|
171
|
+
'value3' => { 'count' => 'count3', 'key_as_string' => 'value3str' }
|
172
|
+
})
|
173
|
+
end
|
174
|
+
|
161
175
|
it "should map a group aggregation response compacted" do
|
162
176
|
agg = GroupAggregation.new :field, compact: true
|
163
177
|
response = { 'buckets' => [
|
164
|
-
{ 'key' => 'value1', 'doc_count' => 'count1' },
|
165
|
-
{ 'key' => 'value2', 'doc_count' => 'count2' },
|
166
|
-
{ 'key' => 'value3', 'doc_count' => 'count3' }
|
178
|
+
{ 'key' => 'value1', 'doc_count' => 'count1', 'key_as_string' => 'value1str' },
|
179
|
+
{ 'key' => 'value2', 'doc_count' => 'count2', 'key_as_string' => 'value2str' },
|
180
|
+
{ 'key' => 'value3', 'doc_count' => 'count3', 'key_as_string' => 'value3str' }
|
167
181
|
] }
|
168
182
|
expect(agg.parse(response)).to eq({
|
169
183
|
'value1' => 'count1',
|
@@ -172,6 +186,16 @@ module Elasticated
|
|
172
186
|
})
|
173
187
|
end
|
174
188
|
|
189
|
+
it "should raise if a group aggregation is compacted but has subaggregations" do
|
190
|
+
agg = GroupAggregation.new(:field, compact: true){ max :other_field }
|
191
|
+
response = { 'buckets' => [
|
192
|
+
{ 'key' => 'value1', 'doc_count' => 'count1', 'key_as_string' => 'value1str' },
|
193
|
+
{ 'key' => 'value2', 'doc_count' => 'count2', 'key_as_string' => 'value2str' },
|
194
|
+
{ 'key' => 'value3', 'doc_count' => 'count3', 'key_as_string' => 'value3str' }
|
195
|
+
] }
|
196
|
+
expect{ agg.parse(response) }.to raise_error RuntimeError
|
197
|
+
end
|
198
|
+
|
175
199
|
end
|
176
200
|
|
177
201
|
describe ValueCountAggregation do
|
@@ -251,12 +275,6 @@ module Elasticated
|
|
251
275
|
expect(agg.build).to eq expected_result
|
252
276
|
end
|
253
277
|
|
254
|
-
it "should build a date histogram aggregation with offset for date" do
|
255
|
-
agg = DateHistogramAggregation.new :date, offset: '+6h'
|
256
|
-
expected_result = { date_histogram: { field: :date, interval: 'day', format: 'yyyy-MM-dd', offset: '+6h' } }
|
257
|
-
expect(agg.build).to eq expected_result
|
258
|
-
end
|
259
|
-
|
260
278
|
it "should build a date histogram aggregation with subaggregations" do
|
261
279
|
agg = DateHistogramAggregation.new :date do |docs|
|
262
280
|
docs.max :numeric_field
|
@@ -474,6 +492,42 @@ module Elasticated
|
|
474
492
|
})
|
475
493
|
end
|
476
494
|
|
495
|
+
it "should map a 'range' response with subaggregations" do
|
496
|
+
agg = RangeAggregation.new :a_field do |a|
|
497
|
+
a.ranges do |r|
|
498
|
+
r.greater_equal :max_value, 'high_values'
|
499
|
+
r.less_equal :min_value
|
500
|
+
r.between :min_value, :max_value
|
501
|
+
end
|
502
|
+
a.max :other_field
|
503
|
+
end
|
504
|
+
response = {
|
505
|
+
'buckets' => {
|
506
|
+
'high_values' => {
|
507
|
+
'from' => 'max_value',
|
508
|
+
'doc_count' => 5,
|
509
|
+
'max_other_field' => { 'value' => 15 }
|
510
|
+
},
|
511
|
+
'less_equal_min_value' => {
|
512
|
+
'to' => 'min_value',
|
513
|
+
'doc_count' => 3,
|
514
|
+
'max_other_field' => { 'value' => 15 }
|
515
|
+
},
|
516
|
+
'between_min_value_and_max_value' => {
|
517
|
+
'from' => 'min_value',
|
518
|
+
'to' => 'max_value',
|
519
|
+
'doc_count' => 9,
|
520
|
+
'max_other_field' => { 'value' => 15 }
|
521
|
+
}
|
522
|
+
}
|
523
|
+
}
|
524
|
+
expect(agg.parse(response)).to eq({
|
525
|
+
'high_values' => { 'count' => 5, 'max_other_field' => 15 },
|
526
|
+
'less_equal_min_value' => { 'count' => 3, 'max_other_field' => 15 },
|
527
|
+
'between_min_value_and_max_value' => { 'count' => 9, 'max_other_field' => 15 }
|
528
|
+
})
|
529
|
+
end
|
530
|
+
|
477
531
|
it "should map a 'range' response compacted" do
|
478
532
|
agg = RangeAggregation.new :a_field, compact: true do |a|
|
479
533
|
a.ranges do |r|
|
@@ -506,6 +560,35 @@ module Elasticated
|
|
506
560
|
})
|
507
561
|
end
|
508
562
|
|
563
|
+
it "should raise on a subaggregated and compacted 'range'" do
|
564
|
+
agg = RangeAggregation.new :a_field, compact: true do |a|
|
565
|
+
a.ranges do |r|
|
566
|
+
r.greater_equal :max_value, 'high_values'
|
567
|
+
r.less_equal :min_value
|
568
|
+
r.between :min_value, :max_value
|
569
|
+
end
|
570
|
+
a.max :other_field
|
571
|
+
end
|
572
|
+
response = {
|
573
|
+
'buckets' => {
|
574
|
+
'high_values' => {
|
575
|
+
'from' => 'max_value',
|
576
|
+
'doc_count' => 5
|
577
|
+
},
|
578
|
+
'less_equal_min_value' => {
|
579
|
+
'to' => 'min_value',
|
580
|
+
'doc_count' => 3
|
581
|
+
},
|
582
|
+
'between_min_value_and_max_value' => {
|
583
|
+
'from' => 'min_value',
|
584
|
+
'to' => 'max_value',
|
585
|
+
'doc_count' => 9
|
586
|
+
}
|
587
|
+
}
|
588
|
+
}
|
589
|
+
expect{ agg.parse(response) }.to raise_error RuntimeError
|
590
|
+
end
|
591
|
+
|
509
592
|
end
|
510
593
|
|
511
594
|
describe SumDistinctAggregation do
|
@@ -550,10 +633,6 @@ module Elasticated
|
|
550
633
|
|
551
634
|
describe TopHitsAggregation do
|
552
635
|
|
553
|
-
def open_response(name)
|
554
|
-
JSON.parse File.read "spec/#{name}.json"
|
555
|
-
end
|
556
|
-
|
557
636
|
it "should build a 'top hits' aggregation" do
|
558
637
|
agg = TopHitsAggregation.new :some_name do |q|
|
559
638
|
q.size 5
|
@@ -0,0 +1,158 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
module Elasticated
|
4
|
+
describe BulkRequest do
|
5
|
+
|
6
|
+
let :repository do
|
7
|
+
Repository.new
|
8
|
+
end
|
9
|
+
|
10
|
+
context "in the index-like actions" do
|
11
|
+
|
12
|
+
let :document do
|
13
|
+
Document.create do |doc|
|
14
|
+
doc.id = '2'
|
15
|
+
doc.type = 'post'
|
16
|
+
doc.index = 'insights'
|
17
|
+
doc.source = { some_field: 'some_value' }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should build an index action (with only a doc)" do
|
22
|
+
action = BulkActions::IndexAction.new repository, document
|
23
|
+
expect(action.build).to eq [
|
24
|
+
{ index: { _index: "insights", _type: "post", _id: "2" } },
|
25
|
+
{ some_field: "some_value" }
|
26
|
+
]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should build an index action (with a doc and other params)" do
|
30
|
+
action = BulkActions::IndexAction.new repository, document, id: "5", type: 'faketype', index: 'fakeindex'
|
31
|
+
expect(action.build).to eq [
|
32
|
+
{ index: { _index: "fakeindex", _type: "faketype", _id: "5" } },
|
33
|
+
{ some_field: "some_value" }
|
34
|
+
]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should build an create action (with only a doc)" do
|
38
|
+
action = BulkActions::CreateAction.new repository, document
|
39
|
+
expect(action.build).to eq [
|
40
|
+
{ create: { _index: "insights", _type: "post", _id: "2" } },
|
41
|
+
{ some_field: "some_value" }
|
42
|
+
]
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should build an create action (with a doc and other params)" do
|
46
|
+
action = BulkActions::CreateAction.new repository, document, id: "5", type: 'faketype', index: 'fakeindex'
|
47
|
+
expect(action.build).to eq [
|
48
|
+
{ create: { _index: "fakeindex", _type: "faketype", _id: "5" } },
|
49
|
+
{ some_field: "some_value" }
|
50
|
+
]
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
context "in the update-like actions" do
|
56
|
+
|
57
|
+
let(:source){ { some_field: 'some_value' } }
|
58
|
+
|
59
|
+
it "should build an update action" do
|
60
|
+
action = BulkActions::UpdateAction.new repository, "2", type: "post", index: "insights", source: source
|
61
|
+
expect(action.build).to eq [
|
62
|
+
{ update: { _index: "insights", _type: "post", _id: "2" } },
|
63
|
+
{ doc: { some_field: "some_value" } }
|
64
|
+
]
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should build an upsert action" do
|
68
|
+
action = BulkActions::UpsertAction.new repository, "2", type: "post", index: "insights", source: source
|
69
|
+
expect(action.build).to eq [
|
70
|
+
{ update: { _index: "insights", _type: "post", _id: "2" } },
|
71
|
+
{ doc: { some_field: "some_value" }, doc_as_upsert: true }
|
72
|
+
]
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
context "in the delete-like actions" do
|
78
|
+
|
79
|
+
it "should build a delete action" do
|
80
|
+
action = BulkActions::DeleteAction.new repository, '2', index: 'insights', type: 'post'
|
81
|
+
expect(action.build).to eq [
|
82
|
+
{ delete: { _index: "insights", _type: "post", _id: "2" } }
|
83
|
+
]
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
context "the bulk request" do
|
89
|
+
|
90
|
+
let :source do
|
91
|
+
{ some_field: 'some_value' }
|
92
|
+
end
|
93
|
+
|
94
|
+
let :document do
|
95
|
+
Document.create do |doc|
|
96
|
+
doc.id = '2'
|
97
|
+
doc.type = 'post'
|
98
|
+
doc.index = 'insights'
|
99
|
+
doc.source = source
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should build a serie of actions correctly" do
|
104
|
+
bulk_request = BulkRequest.build_over repository do |r|
|
105
|
+
r.delete_document "2", type: 'post', index: 'insights'
|
106
|
+
r.create_document document
|
107
|
+
r.update_document "2", type: 'post', index: 'insights', source: source
|
108
|
+
r.index_document document
|
109
|
+
end
|
110
|
+
expect(bulk_request.to_text).to eq \
|
111
|
+
'{"delete":{"_index":"insights","_type":"post","_id":"2"}}' + "\n" +
|
112
|
+
'{"create":{"_index":"insights","_type":"post","_id":"2"}}' + "\n" +
|
113
|
+
'{"some_field":"some_value"}' + "\n" +
|
114
|
+
'{"update":{"_index":"insights","_type":"post","_id":"2"}}' + "\n" +
|
115
|
+
'{"doc":{"some_field":"some_value"}}' + "\n" +
|
116
|
+
'{"index":{"_index":"insights","_type":"post","_id":"2"}}' + "\n" +
|
117
|
+
'{"some_field":"some_value"}'
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should parse a simple response" do
|
121
|
+
elasticsearch_response = open_response 'elasticsearch_bulk_response_1'
|
122
|
+
bulk_request = BulkRequest.build_over repository # actions actually doesnt matter
|
123
|
+
response = bulk_request.parse elasticsearch_response
|
124
|
+
expect(response.errors?).to be false
|
125
|
+
expect(response.items.count).to eql 4
|
126
|
+
item1 = response.items[0]
|
127
|
+
expect(item1.action).to eq 'delete'
|
128
|
+
expect(item1.index).to eq 'website'
|
129
|
+
expect(item1.type).to eq 'blog'
|
130
|
+
expect(item1.id).to eq '123'
|
131
|
+
expect(item1.version).to eql 2
|
132
|
+
expect(item1.status).to eq 200
|
133
|
+
expect(item1.found).to be true
|
134
|
+
expect(item1.error?).to be false
|
135
|
+
expect(item1.completed?).to be true
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should parse a simple response with errors" do
|
139
|
+
elasticsearch_response = open_response 'elasticsearch_bulk_response_2'
|
140
|
+
bulk_request = BulkRequest.build_over repository # actions actually doesnt matter
|
141
|
+
response = bulk_request.parse elasticsearch_response
|
142
|
+
expect(response.errors?).to be true
|
143
|
+
expect(response.items.count).to eql 2
|
144
|
+
item1 = response.items[0]
|
145
|
+
expect(item1.action).to eq 'create'
|
146
|
+
expect(item1.index).to eq 'website'
|
147
|
+
expect(item1.type).to eq 'blog'
|
148
|
+
expect(item1.id).to eq '123'
|
149
|
+
expect(item1.status).to eq 409
|
150
|
+
expect(item1.error).to eq 'DocumentAlreadyExistsException[[website][4] [blog][123]: document already exists]'
|
151
|
+
expect(item1.error?).to be true
|
152
|
+
expect(item1.completed?).to be false
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|