elasticated 2.5.5 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
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