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.
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
@@ -20,7 +20,7 @@ module Elasticated
20
20
  end
21
21
 
22
22
  def parse_subaggregations(response)
23
- if compact and _subaggregations.one?
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 accept_visitor(visitor)
15
- visitor.visit_boolean_clause(self)
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,14 @@
1
+ module Elasticated
2
+ module BulkActions
3
+ class CreateAction < IndexAction
4
+
5
+ protected
6
+
7
+ # override
8
+ def command_name
9
+ :create
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -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,14 @@
1
+ module Elasticated
2
+ module BulkActions
3
+ class UpsertAction < UpdateAction
4
+
5
+ protected
6
+
7
+ # override
8
+ def build_body_from(prepared_source)
9
+ { doc: prepared_source, doc_as_upsert: true }
10
+ end
11
+
12
+ end
13
+ end
14
+ 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
@@ -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 delete(body, opts={})
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 accept_visitor(visitor)
18
- visitor.visit_condition(self)
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 accept_visitor(visitor)
19
- visitor.visit_range(self)
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 accept_visitor(visitor)
21
- visitor.visit_condition(self)
20
+ def fill_delimiter(field_delimiter)
21
+ # nothing to do
22
22
  end
23
23
 
24
24
  end