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
@@ -2,12 +2,46 @@ module Elasticated
2
2
  module Mapping
3
3
  class ObjectBuilder < FieldsBuilder
4
4
 
5
+ attr_accessor :object_attributes
6
+
7
+ def initialize(*args)
8
+ super
9
+ self.object_attributes = Hash.new
10
+ end
11
+
12
+ def add_attribute(name, value)
13
+ object_attributes[name] = value
14
+ end
15
+
16
+ def base_body
17
+ { type: :object }
18
+ end
19
+
5
20
  # override
6
21
  def build_body
7
- {
8
- type: :object,
9
- properties: super
10
- }
22
+ ret = base_body
23
+ properties = super
24
+ ret.merge! properties: properties unless properties.empty?
25
+ ret.merge! object_attributes unless object_attributes.empty?
26
+ ret
27
+ end
28
+
29
+ # 'dynamic' attribute
30
+
31
+ def dynamic(value)
32
+ add_attribute :dynamic, value
33
+ end
34
+
35
+ def strict
36
+ dynamic Enum::Mapping::Dynamic::STRICT
37
+ end
38
+
39
+ def ignore_new_fields
40
+ dynamic Enum::Mapping::Dynamic::IGNORE_NEW_FIELDS
41
+ end
42
+
43
+ def accept_new_fields
44
+ dynamic Enum::Mapping::Dynamic::ACCEPT_NEW_FIELDS
11
45
  end
12
46
 
13
47
  end
@@ -1,12 +1,10 @@
1
1
  module Elasticated
2
2
  module Mapping
3
- class TypeBuilder < FieldsBuilder
3
+ class TypeBuilder < ObjectBuilder
4
4
 
5
5
  # override
6
- def build_body
7
- {
8
- properties: super
9
- }
6
+ def base_body
7
+ Hash.new
10
8
  end
11
9
 
12
10
  end
@@ -0,0 +1,17 @@
1
+ module Elasticated
2
+ module Mixins
3
+ module BlockEvaluation
4
+
5
+ def evaluate(block=nil, obj=nil)
6
+ return unless block
7
+ obj ||= self
8
+ if block.parameters.empty?
9
+ obj.instance_exec &block
10
+ else
11
+ block.call obj
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,60 @@
1
+ module Elasticated
2
+ module Mixins
3
+ module Clonable
4
+
5
+ def clone
6
+ ret = super
7
+ instance_variables.each do |instance_variable|
8
+ value = instance_variable_get instance_variable
9
+ value = case value.class
10
+ when Array
11
+ clone_array value
12
+ when Hash
13
+ Helpers.hash_deep_dup value
14
+ else
15
+ value.clone
16
+ end
17
+ ret.instance_variable_set instance_variable, value
18
+ end
19
+ ret
20
+ end
21
+
22
+ def ==(other_entity)
23
+ other_entity.class == self.class &&
24
+ instance_variables.all? do |instance_variable|
25
+ next true if instance_variable == :@_subaggregations # Subaggregated
26
+ value = instance_variable_get instance_variable
27
+ other_value = other_entity.instance_variable_get instance_variable
28
+ case other_value.class
29
+ when Array
30
+ compare_arrays value, other_value
31
+ else
32
+ other_value == value
33
+ end
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def clone_array(array)
40
+ array.map do |element|
41
+ case element.class
42
+ when Hash
43
+ Helpers.hash_deep_dup element
44
+ when Array
45
+ clone_array element
46
+ else
47
+ element.clone
48
+ end
49
+ end
50
+ end
51
+
52
+ def compare_arrays(array_a, array_b)
53
+ array_a.all? do |element|
54
+ array_b.include? element
55
+ end && array_a.size == array_b.size
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,22 @@
1
+ module Elasticated
2
+ module Mixins
3
+ module Configurable
4
+
5
+ def self.delegated(attr_name)
6
+ define_method attr_name do
7
+ instance_variable_get("@#{attr_name}") || Configuration.send(attr_name)
8
+ end
9
+ define_method "#{attr_name}=" do |value|
10
+ instance_variable_set "@#{attr_name}", value
11
+ end
12
+ end
13
+
14
+ delegated :logger
15
+ alias_method :log, :logger
16
+ delegated :scroll_expiration_time
17
+ delegated :scroll_page_size
18
+ delegated :search_page_size
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ module Elasticated
2
+ module Mixins
3
+ module Inspectionable
4
+
5
+ def inspect(show_original=false)
6
+ return super() if show_original
7
+ "#<#{self.class.name}:#{text_for_inspect}>"
8
+ end
9
+
10
+ def text_for_inspect
11
+ build.to_json # default implementation
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -13,34 +13,40 @@ module Elasticated
13
13
  client.refresh_indices affected_indices
14
14
  end
15
15
 
16
- # override
17
- def execute_aggregations(query, opts={})
18
- super(query, {delimit_by: [:conditions, :aggregations]}.merge(opts))
16
+ def affected_indices_for(query)
17
+ index_selector.indices_for_query(query)
19
18
  end
20
19
 
21
- protected
20
+ def affected_index_for(user_params)
21
+ index_params = user_params.delete(:index_for)
22
+ index_params || raise("The index selection parameters should be specified in the missing 'index_for' option")
23
+ index_selector.index_for_params index_params
24
+ end
25
+
26
+ def params_for_document(document, original_params={})
27
+ affected_index = index_selector.index_for_document document
28
+ original_params.merge index: affected_index
29
+ end
22
30
 
23
- # override
24
- def execute(action, query, opts={})
25
- affected_indices = affected_indices_for query, opts
31
+ def params_for_query(query, original_params={})
32
+ affected_indices = affected_indices_for query
26
33
  affected_indices = affected_indices*','
27
- super action, query, opts.merge(index: affected_indices).reject { |k,_| k == :delimit_by }
34
+ original_params.merge index: affected_indices
28
35
  end
29
36
 
30
- # override
31
- def prepare(action, document, opts={})
32
- affected_index = index_selector.index_for_document(document)
33
- super action, document, opts.merge(index: affected_index)
37
+ def params_for_source(source, original_params={})
38
+ affected_index = affected_index_for original_params
39
+ original_params.merge index: affected_index
34
40
  end
35
41
 
36
- # override
37
- def prepare_percolator(action, query, opts={})
38
- affected_index = index_selector.index_for_percolator(query)
39
- super action, query, opts.merge(index: affected_index)
42
+ def params_for_ids(ids, original_params={})
43
+ affected_index = affected_index_for original_params
44
+ original_params.merge index: affected_index
40
45
  end
41
46
 
42
- def affected_indices_for(query, opts={})
43
- index_selector.indices_for_query(query, opts)
47
+ def params_for_percolator(original_params={})
48
+ affected_index = index_selector.index_for_percolator
49
+ original_params.merge index: affected_index
44
50
  end
45
51
 
46
52
  end
@@ -9,8 +9,9 @@ module Elasticated
9
9
  end
10
10
  end
11
11
 
12
- include BlockEvaluation
13
- include Clonable
12
+ include Mixins::Clonable
13
+ include Mixins::BlockEvaluation
14
+ include Mixins::Inspectionable
14
15
 
15
16
  attr_accessor :_conditions, :_filter_conditions, :_post_conditions
16
17
  attr_accessor :_source, :_sort, :_size, :_from
@@ -53,35 +54,38 @@ module Elasticated
53
54
  end
54
55
  alias_method :offset, :from
55
56
 
56
- def custom_sort(custom_hash)
57
+ def sort(field, method=nil)
57
58
  self._sort ||= Array.new
58
- _sort << custom_hash
59
+ _sort << { field => { order: method || :asc } }
59
60
  self
60
61
  end
61
62
 
62
- def sort(field, method=nil)
63
- custom_sort(field => { order: method || :asc })
64
- end
65
- alias_method :sort_by_field, :sort
66
-
67
- def sort_by_script(script_hash)
68
- custom_sort(_script: script_hash)
69
- end
70
-
71
63
  def sort_randomly
72
- sort_by_script(script: "Math.random()", type: "number")
64
+ self._sort ||= Array.new
65
+ _sort << { _script: { script: "Math.random()", type: "number" } }
66
+ self
73
67
  end
74
68
 
75
69
  def source(*fields_array)
76
- self._source = fields_array.flatten
70
+ if fields_array.count == 1 && fields_array.first == false
71
+ no_source
72
+ else
73
+ self._source = fields_array.flatten
74
+ end
77
75
  self
78
76
  end
79
77
  alias_method :fields, :source
80
78
 
79
+ def no_source
80
+ self._source = false
81
+ self
82
+ end
83
+
81
84
  def aggregations(&block)
82
85
  _aggregations.evaluate block
83
86
  self
84
87
  end
88
+ alias_method :aggs, :aggregations
85
89
 
86
90
  # misc getters
87
91
 
@@ -93,7 +97,7 @@ module Elasticated
93
97
  !_size || _size > repository.search_page_size
94
98
  end
95
99
 
96
- def has_offset?
100
+ def offset?
97
101
  _from && _from > 0
98
102
  end
99
103
 
@@ -127,7 +131,7 @@ module Elasticated
127
131
  ret.merge! sort: _sort if _sort
128
132
  ret.merge! size: _size if _size
129
133
  ret.merge! from: _from if _from
130
- ret.merge! _source: _source if _source
134
+ ret.merge! _source: _source unless _source.nil? # source can be false
131
135
  ret
132
136
  end
133
137
 
@@ -143,6 +147,7 @@ module Elasticated
143
147
  ret
144
148
  end
145
149
  alias_method :build, :build_for_aggregated_search
150
+ alias_method :to_h, :build_for_aggregated_search
146
151
 
147
152
  # parse methods
148
153
 
@@ -150,10 +155,11 @@ module Elasticated
150
155
  _aggregations.parse response
151
156
  end
152
157
 
153
- # visitor methods
154
-
155
- def accept_visitor(visitor)
156
- visitor.visit_query(self)
158
+ # delimiters
159
+
160
+ def fill_delimiter(field_delimiter)
161
+ _conditions.fill_delimiter field_delimiter
162
+ _filter_conditions.fill_delimiter field_delimiter
157
163
  end
158
164
 
159
165
  # conditions & filter shorthands
@@ -4,8 +4,9 @@ module Elasticated
4
4
  extend Forwardable
5
5
  def_delegators :@_aggregations, :first, :one?, :empty?
6
6
 
7
- include Clonable
8
- include BlockEvaluation
7
+ include Mixins::Clonable
8
+ include Mixins::BlockEvaluation
9
+ include Mixins::Inspectionable
9
10
 
10
11
  attr_accessor :_aggregations
11
12
 
@@ -27,19 +28,16 @@ module Elasticated
27
28
  end
28
29
  end
29
30
 
30
- def merge!(other_query_aggs)
31
+ def merge! other_query_aggs
31
32
  other_query_aggs._aggregations.each do |other_aggregation|
32
33
  add_aggregation other_aggregation
33
34
  end
34
35
  end
35
36
 
36
- def accept_visitor(visitor)
37
- visitor.visit_query_aggregations(self)
38
- end
39
-
40
37
  private
41
38
 
42
39
  def get_aggregation_class(agg_name)
40
+ return GroupAggregation if agg_name.to_s == 'terms'
43
41
  camel_case_name = Helpers.string_to_camel_case agg_name.to_s
44
42
  self.class.const_get("::Elasticated::#{camel_case_name}Aggregation") rescue nil
45
43
  end
@@ -1,7 +1,8 @@
1
1
  module Elasticated
2
2
  class QueryConditions
3
3
 
4
- include Clonable
4
+ include Mixins::Clonable
5
+ include Mixins::Inspectionable
5
6
 
6
7
  attr_accessor :_must, :_must_not, :_should, :_minimum_should_match, :_cache
7
8
 
@@ -11,8 +12,10 @@ module Elasticated
11
12
  self._should = BooleanClause.new
12
13
  end
13
14
 
14
- def accept_visitor(visitor)
15
- visitor.visit_query_conditions(self)
15
+ # delimiters
16
+
17
+ def fill_delimiter(field_delimiter)
18
+ _must.fill_delimiter field_delimiter
16
19
  end
17
20
 
18
21
  # conditions
@@ -0,0 +1,7 @@
1
+ require 'elasticated'
2
+
3
+ Elasticated.configure do |config|
4
+ config.logger = Elasticated::Loggers::DefaultLogger.new
5
+ end
6
+
7
+ include Elasticated
@@ -1,9 +1,17 @@
1
1
  module Elasticated
2
2
  class Repository
3
- include Configurable
4
-
5
- # child can implement 'execute(action, query, opts)'
6
- # child can implement 'prepare(action, document, opts)'
3
+ include Mixins::Configurable
4
+
5
+ # PRE-ACTION METHODS ----------------------------------------------------------
6
+ # child can implement params_for_document(document, original_params={}) => Hash
7
+ # child can implement params_for_query(query, original_params={}) => Hash
8
+ # child can implement params_for_source(source, original_params={}) => Hash
9
+ # child can implement params_for_ids(ids, original_params={}) => Hash
10
+ # child can implement params_for_percolator(original_params={}) => Hash
11
+ # POST-ACTION METHODS ---------------------------------------------------------
12
+ # child can implement prepare_source(source) => Hash
13
+ # child can implement restore_source(source) => Hash
14
+ # -----------------------------------------------------------------------------
7
15
 
8
16
  attr_accessor :client
9
17
 
@@ -12,76 +20,136 @@ module Elasticated
12
20
  end
13
21
 
14
22
  def execute_search(query, opts={})
15
- execute :search, query, opts
23
+ prepare_query_action :search, query, opts
16
24
  end
17
25
 
18
26
  def execute_aggregations(query, opts={})
19
- execute :aggregations, query, opts
27
+ prepare_query_action :aggregations, query, opts
20
28
  end
21
29
 
22
30
  def execute_count(query, opts={})
23
- execute :count, query, opts
31
+ prepare_query_action :count, query, opts
24
32
  end
25
33
 
26
34
  def execute_aggregated_search(query, opts={})
27
- execute :aggregated_search, query, opts
35
+ prepare_query_action :aggregated_search, query, opts
28
36
  end
29
37
 
30
- def delete_by(query, opts={})
31
- execute :delete, query, opts
38
+ def delete_by_query(query, opts={})
39
+ prepare_query_action :delete_by_query, query, opts
32
40
  end
41
+ alias_method :delete_by, :delete_by_query
33
42
 
34
43
  def exists?(query, opts={})
35
44
  execute_count(query, opts) > 0
36
45
  end
37
46
 
38
47
  def index_document(document, opts={})
39
- prepare :index, document, opts
48
+ prepare_document_action :index_document, document, opts
40
49
  end
41
50
 
42
- def update_document(document, opts={})
43
- prepare :update, document, opts
51
+ def update_document(document_id, opts={})
52
+ source = opts.delete(:source) || raise("No body specified for partial update")
53
+ prepare_source_action :update_document, source, opts.merge(id: document_id)
44
54
  end
45
55
 
46
56
  def create_percolator(query, opts={})
47
- prepare_percolator :create_percolator, query, opts
57
+ prepare_query_action :prepare_percolator_action, query, opts
58
+ end
59
+
60
+ def percolate_document(document, opts={})
61
+ prepare_document_action :prepare_percolator_action, document, opts
62
+ end
63
+
64
+ def get_document(document_id_or_ids, opts={})
65
+ prepare_ids_action :variable_get, Array(document_id_or_ids), opts
48
66
  end
67
+ alias_method :get_documents, :get_document
49
68
 
50
- def percolate(document, opts={})
51
- prepare_percolator :percolate, document, opts
69
+ def delete_document(document_id, opts={})
70
+ prepare_ids_action :delete_document, Array(document_id), opts
52
71
  end
53
72
 
54
73
  def prepare_search(query, opts={})
55
- execute :prepare_search, query, opts
74
+ prepare_query_action :prepare_search, query, opts
56
75
  end
57
76
 
58
77
  def restore_search(scroll_id)
59
78
  ResumableSearch.from_scroll_id self, scroll_id
60
79
  end
61
80
 
62
- protected
81
+ def prepare_bulk(&block)
82
+ BulkRequest.build_over(self, &block)
83
+ end
63
84
 
64
- # write actions
85
+ def execute_bulk(bulk_request)
86
+ result = client.bulk bulk_request.build
87
+ bulk_request.parse result
88
+ end
89
+
90
+ # params preparation
91
+
92
+ def params_for_document(document, original_params={})
93
+ original_params
94
+ end
65
95
 
66
- def _exec_index(document, opts={})
67
- _exec_upsert :index, document, opts
96
+ def params_for_query(query, original_params={})
97
+ original_params
68
98
  end
69
99
 
70
- def _exec_update(document, opts={})
71
- _exec_upsert :update, document, opts
100
+ def params_for_source(source, original_params={})
101
+ original_params
72
102
  end
73
103
 
74
- def _exec_upsert(method, document, opts={})
104
+ def params_for_ids(ids, original_params={})
105
+ original_params
106
+ end
107
+
108
+ def params_for_percolator(original_params={})
109
+ original_params
110
+ end
111
+
112
+ # document translation
113
+
114
+ def prepare_source(source)
115
+ source
116
+ end
117
+
118
+ def restore_source(source)
119
+ source
120
+ end
121
+
122
+ def prepare_document(document)
123
+ params = params_for_document document
124
+ translated_document = document.clone
125
+ translated_document.source = prepare_source Helpers.hash_deep_dup document.source
126
+ translated_document.index = params[:index] if params[:index]
127
+ translated_document.type = params[:type] if params[:type]
128
+ translated_document
129
+ end
130
+
131
+ protected
132
+
133
+ # write actions
134
+
135
+ def _exec_index_document(document, opts={})
75
136
  opts.merge! id: document.id if document.id
76
137
  opts.merge! type: document.type unless opts[:type]
77
138
  opts.merge! index: document.index unless opts[:index]
78
- document.index = opts[:index]
79
- document.type = opts[:type]
80
- client.send "#{method}_document", document.source, opts
139
+ document.index = opts[:index] || raise("A target index should be specified in a indexation")
140
+ document.type = opts[:type] || raise("A target type should be specified in a indexation")
141
+ client.index_document document.source, opts
142
+ end
143
+
144
+ def _exec_update_document(source, opts={})
145
+ opts[:index] || raise("A target index should be specified in a partial update")
146
+ opts[:type] || raise("A target type should be specified in a partial update")
147
+ opts[:id] || raise("A target document id should be specified in a partial update")
148
+ client.update_document source, opts
81
149
  end
82
150
 
83
151
  def _exec_create_percolator(query, opts={})
84
- query_source = query.build.fetch(:query)
152
+ query_source = query.build_for_count
85
153
  client.create_percolator query_source, opts
86
154
  end
87
155
 
@@ -107,8 +175,9 @@ module Elasticated
107
175
  _exec_paginated_search query, query.aggregated?, opts
108
176
  end
109
177
 
110
- def _exec_delete(query, opts={})
111
- client.delete query, opts
178
+ def _exec_delete_by_query(query, opts={})
179
+ body = query.build_for_count
180
+ client.delete_by_query body, opts
112
181
  end
113
182
 
114
183
  def _exec_paginated_search(query, aggregated, opts={})
@@ -134,30 +203,105 @@ module Elasticated
134
203
 
135
204
  def _exec_prepare_search(query, opts={})
136
205
  raise "The query for a resumable search should not have the parameter 'size'" if query.limited? || opts[:size]
137
- raise "The query for a resumable search should not have the parameter 'from'" if query.has_offset? || opts[:from]
206
+ raise "The query for a resumable search should not have the parameter 'from'" if query.offset? || opts[:from]
138
207
  ResumableSearch.new self, query, false, opts
139
208
  end
140
209
 
141
- def _exec_percolate(document, opts={})
142
- document_source = document.document_source
210
+ def _exec_percolate_document(document, opts={})
211
+ document_source = document.source
143
212
  client.percolate document_source, opts
144
213
  end
145
214
 
146
- # abstract methods
215
+ def _exec_get_document(document_id, opts={})
216
+ result = client.get_document document_id, opts
217
+ return nil unless result['found']
218
+ document = Document.parse result
219
+ prepare_served_document document
220
+ end
221
+
222
+ def _exec_get_documents(documents_ids, opts={})
223
+ result = client.get_documents documents_ids, opts
224
+ result['docs'].map do |e|
225
+ document = Document.parse e
226
+ prepare_served_document document
227
+ end
228
+ end
229
+
230
+ def _exec_variable_get(documents_ids, opts={})
231
+ if documents_ids.empty?
232
+ raise "At least one document id must be specified for a get"
233
+ elsif documents_ids.count == 1
234
+ _exec_get_document documents_ids.first, opts
235
+ else
236
+ _exec_get_documents documents_ids, opts
237
+ end
238
+ end
239
+
240
+ def _exec_delete_document(documents_ids, opts={})
241
+ raise "Not more than one document delete per time allowed" unless documents_ids.count == 1
242
+ client.delete_document documents_ids.first, opts
243
+ end
244
+
245
+ # pre-action methods
246
+
247
+ def prepare_source_action(action, source, opts={})
248
+ # child's implementation here
249
+ # child's implementation must end with a 'super' call
250
+ prepared_source = prepare_source Helpers.hash_deep_dup source
251
+ prepared_params = params_for_source source, opts
252
+ send "_exec_#{action}", prepared_source, prepared_params
253
+ end
254
+
255
+ def prepare_ids_action(action, documents_ids, opts={})
256
+ # child's implementation here
257
+ # child's implementation must end with a 'super' call
258
+ prepared_params = params_for_ids documents_ids, opts
259
+ send "_exec_#{action}", documents_ids, prepared_params
260
+ end
261
+
262
+ def prepare_query_action(action, query, opts={})
263
+ # child's implementation here
264
+ # child's implementation must end with a 'super' call
265
+ prepared_params = params_for_query query, opts
266
+ return prepare_percolator_action(:create_percolator, query, prepared_params) if percolator_action?(action)
267
+ send "_exec_#{action}", query, prepared_params
268
+ end
269
+
270
+ def prepare_document_action(action, document, opts={})
271
+ # child's implementation here
272
+ # child's implementation must end with a 'super' call
273
+ prepared_params = params_for_document document, opts
274
+ prepared_document = prepare_document document
275
+ return prepare_percolator_action :percolate_document, prepared_document, prepared_params if percolator_action? action
276
+ send "_exec_#{action}", prepared_document, prepared_params
277
+ end
147
278
 
148
- def execute(action, query, opts={})
279
+ def prepare_percolator_action(action, doc_or_query, opts={})
149
280
  # child's implementation here
150
- send "_exec_#{action}", query, opts
281
+ # child's implementation must end with a 'super' call
282
+ # DO NOT TOUCH THE DOC OR QUERY HERE! use prepare_query_action or prepare_document_action
283
+ prepared_params = params_for_percolator opts
284
+ send "_exec_#{action}", doc_or_query, prepared_params
151
285
  end
152
286
 
153
- def prepare(action, document, opts={})
287
+ # post-action methods
288
+
289
+ def prepare_served_document(document)
154
290
  # child's implementation here
155
- send "_exec_#{action}", document, opts
291
+ document.source = restore_source document.source
292
+ document
156
293
  end
157
294
 
158
- def prepare_percolator(action, query, opts={})
295
+ def prepare_served_results(results)
159
296
  # child's implementation here
160
- send "_exec_#{action}", query, opts
297
+ results.documents.each{ |document| prepare_served_document document }
298
+ results
299
+ end
300
+
301
+ # misc
302
+
303
+ def percolator_action?(action)
304
+ action == :prepare_percolator_action
161
305
  end
162
306
 
163
307
  end