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
@@ -20,7 +20,7 @@ module Elasticated
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def parse_subaggregations(response)
|
23
|
-
if compact and _subaggregations.
|
23
|
+
if compact and _subaggregations.count == 1
|
24
24
|
single_subaggregation = _subaggregations.first
|
25
25
|
single_subaggregation.parse(response[single_subaggregation.name.to_s])
|
26
26
|
else
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Elasticated
|
2
2
|
class BooleanClause
|
3
3
|
|
4
|
-
include Clonable
|
4
|
+
include Mixins::Clonable
|
5
|
+
include Mixins::Inspectionable
|
5
6
|
|
6
7
|
attr_accessor :conditions
|
7
8
|
|
@@ -11,8 +12,8 @@ module Elasticated
|
|
11
12
|
|
12
13
|
# delimiters
|
13
14
|
|
14
|
-
def
|
15
|
-
|
15
|
+
def fill_delimiter(field_delimiter)
|
16
|
+
conditions.each{ |condition| condition.fill_delimiter field_delimiter }
|
16
17
|
end
|
17
18
|
|
18
19
|
# conditions
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Elasticated
|
2
|
+
module BulkActions
|
3
|
+
class DeleteAction < StandardAction
|
4
|
+
|
5
|
+
attr_accessor :document_id, :params
|
6
|
+
|
7
|
+
def initialize(repository, document_id, params={})
|
8
|
+
super repository
|
9
|
+
self.document_id = document_id
|
10
|
+
self.params = params
|
11
|
+
end
|
12
|
+
|
13
|
+
def build
|
14
|
+
original_params = Helpers.hash_deep_dup params
|
15
|
+
# preparations
|
16
|
+
prepared_params = repository.params_for_ids [document_id], original_params
|
17
|
+
# verifications
|
18
|
+
prepared_params[:index] || raise("A target index should be specified in a delete")
|
19
|
+
prepared_params[:type] || raise("A target type should be specified in a delete")
|
20
|
+
# the final command
|
21
|
+
prepared_params[:_index] = prepared_params.delete :index
|
22
|
+
prepared_params[:_type] = prepared_params.delete :type
|
23
|
+
prepared_params[:_id] = document_id
|
24
|
+
command = { delete: prepared_params }
|
25
|
+
[command]
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Elasticated
|
2
|
+
module BulkActions
|
3
|
+
class IndexAction < StandardAction
|
4
|
+
|
5
|
+
attr_accessor :document, :params
|
6
|
+
|
7
|
+
def initialize(repository, document, params={})
|
8
|
+
super repository
|
9
|
+
self.document = document
|
10
|
+
self.params = params
|
11
|
+
end
|
12
|
+
|
13
|
+
def build
|
14
|
+
original_params = Helpers.hash_deep_dup params
|
15
|
+
# preparations
|
16
|
+
prepared_document = repository.prepare_document document
|
17
|
+
prepared_params = repository.params_for_document document, original_params
|
18
|
+
# the final command
|
19
|
+
prepared_params[:_index] = prepared_params.delete(:index) || prepared_document.index || raise("An index name is required for a document indexation")
|
20
|
+
prepared_params[:_type] = prepared_params.delete(:type) || prepared_document.type || raise("A type name is required for a document indexation")
|
21
|
+
prepared_params[:_id] = prepared_params.delete(:id) || prepared_document.id
|
22
|
+
command = { command_name => prepared_params }
|
23
|
+
prepared_source = prepared_document.source
|
24
|
+
[command, prepared_source]
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def command_name
|
30
|
+
:index
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Elasticated
|
2
|
+
module BulkActions
|
3
|
+
class StandardAction
|
4
|
+
|
5
|
+
# abstract class
|
6
|
+
# child must implement 'build()' => Hash
|
7
|
+
|
8
|
+
attr_accessor :repository
|
9
|
+
|
10
|
+
def initialize(repository)
|
11
|
+
self.repository = repository
|
12
|
+
end
|
13
|
+
|
14
|
+
# def build
|
15
|
+
# command = build_command
|
16
|
+
# body = build_body
|
17
|
+
# [command, body]
|
18
|
+
# end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Elasticated
|
2
|
+
module BulkActions
|
3
|
+
class UpdateAction < StandardAction
|
4
|
+
|
5
|
+
attr_accessor :document_id, :params
|
6
|
+
|
7
|
+
def initialize(repository, document_id, params={})
|
8
|
+
super repository
|
9
|
+
self.document_id = document_id
|
10
|
+
self.params = params
|
11
|
+
end
|
12
|
+
|
13
|
+
def build
|
14
|
+
original_params = Helpers.hash_deep_dup params
|
15
|
+
# verifications
|
16
|
+
source = original_params.delete(:source) || raise("No body specified for partial update")
|
17
|
+
# preparations
|
18
|
+
prepared_source = repository.prepare_source Helpers.hash_deep_dup source
|
19
|
+
prepared_params = repository.params_for_source source, original_params
|
20
|
+
# more verifications
|
21
|
+
prepared_params[:index] || raise("A target index should be specified in a partial update")
|
22
|
+
prepared_params[:type] || raise("A target type should be specified in a partial update")
|
23
|
+
# the final command
|
24
|
+
prepared_params[:_index] = prepared_params.delete :index
|
25
|
+
prepared_params[:_type] = prepared_params.delete :type
|
26
|
+
prepared_params[:_id] = document_id
|
27
|
+
command = { command_name => prepared_params }
|
28
|
+
body = build_body_from prepared_source
|
29
|
+
[command, body]
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
def command_name
|
35
|
+
:update
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_body_from(prepared_source)
|
39
|
+
{ doc: prepared_source }
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Elasticated
|
2
|
+
class BulkRequest
|
3
|
+
|
4
|
+
def self.build_over(repository, &block)
|
5
|
+
request = new repository
|
6
|
+
request.evaluate block
|
7
|
+
request
|
8
|
+
end
|
9
|
+
|
10
|
+
include Mixins::Inspectionable
|
11
|
+
include Mixins::BlockEvaluation
|
12
|
+
|
13
|
+
attr_accessor :repository, :actions
|
14
|
+
attr_accessor :errors, :items
|
15
|
+
|
16
|
+
def initialize(repository)
|
17
|
+
self.repository = repository
|
18
|
+
self.actions = Array.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def add(action)
|
22
|
+
actions << action
|
23
|
+
end
|
24
|
+
|
25
|
+
def build
|
26
|
+
actions.map(&:build).flatten
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_text
|
30
|
+
build.map(&:to_json)*"\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_action_class(action_name)
|
34
|
+
return nil unless action_name.to_s.end_with? '_document'
|
35
|
+
camel_case_name = Helpers.string_to_camel_case action_name.to_s.gsub /\_document$/, ''
|
36
|
+
self.class.const_get("::Elasticated::BulkActions::#{camel_case_name}Action") rescue nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(method_name, *args, &block)
|
40
|
+
action_class = get_action_class method_name
|
41
|
+
if action_class
|
42
|
+
action = action_class.new(repository, *args, &block)
|
43
|
+
add action
|
44
|
+
else
|
45
|
+
super
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def respond_to_missing?(name, include_private=false)
|
50
|
+
get_action_class(name) || super
|
51
|
+
end
|
52
|
+
|
53
|
+
def parse(result)
|
54
|
+
Response.parse result
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Elasticated
|
2
|
+
class BulkRequest
|
3
|
+
class Response
|
4
|
+
|
5
|
+
include Mixins::Inspectionable
|
6
|
+
|
7
|
+
def self.parse(elasticsearch_response)
|
8
|
+
response = new
|
9
|
+
response.took = elasticsearch_response['took']
|
10
|
+
response.errors = elasticsearch_response['errors']
|
11
|
+
response.items = elasticsearch_response['items'].map do |elasticsearch_item|
|
12
|
+
ResponseItem.parse elasticsearch_item
|
13
|
+
end
|
14
|
+
response
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_accessor :took, :errors, :items
|
18
|
+
|
19
|
+
def errors?
|
20
|
+
!!errors
|
21
|
+
end
|
22
|
+
alias_method :error?, :errors?
|
23
|
+
|
24
|
+
def text_for_inspect
|
25
|
+
text = (items.count == 1) ? "#{items.count} item" : "#{items.count} items"
|
26
|
+
text = errors? ? "#{text}, with errors" : "#{text}, no errors"
|
27
|
+
text
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Elasticated
|
2
|
+
class BulkRequest
|
3
|
+
class ResponseItem
|
4
|
+
|
5
|
+
include Mixins::Inspectionable
|
6
|
+
|
7
|
+
def self.parse(partial_response)
|
8
|
+
item = new
|
9
|
+
item.action = partial_response.first.first
|
10
|
+
data = partial_response.first.last
|
11
|
+
item.index = data['_index']
|
12
|
+
item.type = data['_type']
|
13
|
+
item.id = data['_id']
|
14
|
+
item.version = data['_version']
|
15
|
+
item.status = data['status']
|
16
|
+
item.found = data['found']
|
17
|
+
item.error = data['error']
|
18
|
+
item
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_accessor :action, :index, :type, :id, :version, :status, :found, :error
|
22
|
+
|
23
|
+
def error?
|
24
|
+
!!error
|
25
|
+
end
|
26
|
+
|
27
|
+
def completed?
|
28
|
+
!error?
|
29
|
+
end
|
30
|
+
|
31
|
+
def text_for_inspect
|
32
|
+
text = "#{action} #{index}/#{type}/#{id} (status #{status})"
|
33
|
+
text = "#{text}, with error" if error?
|
34
|
+
text
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/elasticated/client.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Elasticated
|
2
2
|
class Client
|
3
|
-
include Configurable
|
3
|
+
include Mixins::Configurable
|
4
4
|
|
5
5
|
attr_accessor :transport
|
6
6
|
|
@@ -41,7 +41,7 @@ module Elasticated
|
|
41
41
|
mapping = opts[:mapping]
|
42
42
|
body = Hash.new
|
43
43
|
body.merge!(settings: { number_of_shards: shards }) if shards
|
44
|
-
body.merge!(mappings: mapping) if mapping
|
44
|
+
body.merge!(mappings: mapping.to_h) if mapping # both Hash and Mapping::Builder responds to 'to_h'
|
45
45
|
args.merge! body: body unless body.empty?
|
46
46
|
log.info "Creating index '#{index_name}'"
|
47
47
|
transport.indices.create args
|
@@ -65,6 +65,10 @@ module Elasticated
|
|
65
65
|
log.info "Alias '#{index_alias}' removed from index '#{index_name}'"
|
66
66
|
end
|
67
67
|
|
68
|
+
def update_mapping(index_name, type_name, mapping, opts={})
|
69
|
+
transport.indices.put_mapping opts.merge(index: index_name, type: type_name, body: mapping)
|
70
|
+
end
|
71
|
+
|
68
72
|
def refresh_index(index_name)
|
69
73
|
transport.indices.refresh index: index_name
|
70
74
|
log.debug "Index '#{index_name}' refreshed"
|
@@ -95,11 +99,31 @@ module Elasticated
|
|
95
99
|
transport.scroll opts.merge scroll_id: scroll_id
|
96
100
|
end
|
97
101
|
|
98
|
-
def
|
102
|
+
def delete_by_query(body, opts={})
|
99
103
|
log_query :delete, body.to_json, opts
|
100
104
|
transport.delete_by_query opts.merge body: body
|
101
105
|
end
|
102
106
|
|
107
|
+
def get_document(document_id, opts={})
|
108
|
+
log_query :get, document_id, opts
|
109
|
+
transport.get opts.merge id: document_id
|
110
|
+
end
|
111
|
+
|
112
|
+
def get_documents(documents_ids, opts={})
|
113
|
+
log_query :mget, documents_ids, opts
|
114
|
+
transport.mget opts.merge body: { ids: documents_ids }
|
115
|
+
end
|
116
|
+
|
117
|
+
def delete_document(document_id, opts={})
|
118
|
+
log_query :delete, document_id, opts
|
119
|
+
transport.delete opts.merge id: document_id
|
120
|
+
end
|
121
|
+
|
122
|
+
def bulk(bulk_body, opts={})
|
123
|
+
log_query :bulk, bulk_body, opts
|
124
|
+
transport.bulk opts.merge body: bulk_body
|
125
|
+
end
|
126
|
+
|
103
127
|
protected
|
104
128
|
|
105
129
|
def log_query(query_type, message_body, query_opts={})
|
@@ -2,7 +2,7 @@ module Elasticated
|
|
2
2
|
module Conditions
|
3
3
|
class CustomCondition
|
4
4
|
|
5
|
-
include Inspectionable
|
5
|
+
include Mixins::Inspectionable
|
6
6
|
|
7
7
|
attr_accessor :body
|
8
8
|
|
@@ -14,8 +14,8 @@ module Elasticated
|
|
14
14
|
body
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
18
|
-
|
17
|
+
def fill_delimiter(field_delimiter)
|
18
|
+
# nothing to do
|
19
19
|
end
|
20
20
|
|
21
21
|
end
|
@@ -15,8 +15,11 @@ module Elasticated
|
|
15
15
|
{ range: { field => body }.merge(opts) }
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
|
18
|
+
def fill_delimiter(field_delimiter)
|
19
|
+
minimum_value = body[:gt] || body[:gte]
|
20
|
+
field_delimiter.set_minimum field, minimum_value
|
21
|
+
maximum_value = body[:lt] || body[:lte]
|
22
|
+
field_delimiter.set_maximum field, maximum_value
|
20
23
|
end
|
21
24
|
|
22
25
|
end
|
@@ -2,7 +2,7 @@ module Elasticated
|
|
2
2
|
module Conditions
|
3
3
|
class ScriptCondition
|
4
4
|
|
5
|
-
include Inspectionable
|
5
|
+
include Mixins::Inspectionable
|
6
6
|
|
7
7
|
attr_accessor :script, :params
|
8
8
|
|
@@ -17,8 +17,8 @@ module Elasticated
|
|
17
17
|
{ script: body }
|
18
18
|
end
|
19
19
|
|
20
|
-
def
|
21
|
-
|
20
|
+
def fill_delimiter(field_delimiter)
|
21
|
+
# nothing to do
|
22
22
|
end
|
23
23
|
|
24
24
|
end
|