elasticated 1.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 (83) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/Gemfile +4 -0
  4. data/README.md +3 -0
  5. data/Rakefile +6 -0
  6. data/elasticated.gemspec +29 -0
  7. data/lib/elasticated.rb +102 -0
  8. data/lib/elasticated/aggregation.rb +36 -0
  9. data/lib/elasticated/aggregations/cardinality_aggregation.rb +15 -0
  10. data/lib/elasticated/aggregations/count_aggregation.rb +15 -0
  11. data/lib/elasticated/aggregations/count_distinct_aggregation.rb +15 -0
  12. data/lib/elasticated/aggregations/count_filtered_aggregation.rb +29 -0
  13. data/lib/elasticated/aggregations/custom_aggregation.rb +25 -0
  14. data/lib/elasticated/aggregations/date_histogram_aggregation.rb +35 -0
  15. data/lib/elasticated/aggregations/filter_aggregation.rb +33 -0
  16. data/lib/elasticated/aggregations/filter_aggregation_evaluator.rb +22 -0
  17. data/lib/elasticated/aggregations/group_aggregation.rb +29 -0
  18. data/lib/elasticated/aggregations/histogram_aggregation.rb +34 -0
  19. data/lib/elasticated/aggregations/nested_aggregation.rb +30 -0
  20. data/lib/elasticated/aggregations/range_aggregation.rb +35 -0
  21. data/lib/elasticated/aggregations/range_aggregation_evaluator.rb +22 -0
  22. data/lib/elasticated/aggregations/ranges_builder.rb +35 -0
  23. data/lib/elasticated/aggregations/single_value_aggregation.rb +47 -0
  24. data/lib/elasticated/aggregations/subaggregated.rb +27 -0
  25. data/lib/elasticated/aggregations/sum_distinct_aggregation.rb +20 -0
  26. data/lib/elasticated/aggregations/terms_aggregation.rb +63 -0
  27. data/lib/elasticated/aggregations/top_hits_aggregation.rb +25 -0
  28. data/lib/elasticated/block_evaluation.rb +15 -0
  29. data/lib/elasticated/boolean_clause.rb +43 -0
  30. data/lib/elasticated/client.rb +84 -0
  31. data/lib/elasticated/clonable.rb +58 -0
  32. data/lib/elasticated/conditions/custom_condition.rb +19 -0
  33. data/lib/elasticated/conditions/exists_condition.rb +11 -0
  34. data/lib/elasticated/conditions/missing_condition.rb +11 -0
  35. data/lib/elasticated/conditions/nested_condition.rb +19 -0
  36. data/lib/elasticated/conditions/range_condition.rb +27 -0
  37. data/lib/elasticated/conditions/script_condition.rb +22 -0
  38. data/lib/elasticated/conditions/standard_condition.rb +26 -0
  39. data/lib/elasticated/conditions/terms_condition.rb +22 -0
  40. data/lib/elasticated/conditions/wildcard_condition.rb +18 -0
  41. data/lib/elasticated/conditions_builder.rb +75 -0
  42. data/lib/elasticated/configurable.rb +9 -0
  43. data/lib/elasticated/configuration.rb +9 -0
  44. data/lib/elasticated/default_logger.rb +27 -0
  45. data/lib/elasticated/delimiters/date_field_delimiter.rb +33 -0
  46. data/lib/elasticated/delimiters/standard_field_delimiter.rb +33 -0
  47. data/lib/elasticated/delimiters/term_field_delimiter.rb +24 -0
  48. data/lib/elasticated/document.rb +46 -0
  49. data/lib/elasticated/helpers.rb +28 -0
  50. data/lib/elasticated/index_selector.rb +44 -0
  51. data/lib/elasticated/inspectionable.rb +9 -0
  52. data/lib/elasticated/mapping.rb +19 -0
  53. data/lib/elasticated/mapping/builder.rb +36 -0
  54. data/lib/elasticated/mapping/fields_builder.rb +148 -0
  55. data/lib/elasticated/mapping/nested_builder.rb +15 -0
  56. data/lib/elasticated/mapping/object_builder.rb +15 -0
  57. data/lib/elasticated/mapping/partial.rb +11 -0
  58. data/lib/elasticated/mapping/type_builder.rb +14 -0
  59. data/lib/elasticated/partitioned_repository.rb +27 -0
  60. data/lib/elasticated/query.rb +159 -0
  61. data/lib/elasticated/query_aggregations.rb +71 -0
  62. data/lib/elasticated/query_conditions.rb +89 -0
  63. data/lib/elasticated/repositories/monthly_partitioned_repository.rb +96 -0
  64. data/lib/elasticated/repository.rb +139 -0
  65. data/lib/elasticated/results.rb +43 -0
  66. data/lib/version.rb +92 -0
  67. data/spec/aggregation_spec.rb +587 -0
  68. data/spec/date_field_delimiter_spec.rb +67 -0
  69. data/spec/document_spec.rb +44 -0
  70. data/spec/elasticsearch_hit_1.json +14 -0
  71. data/spec/elasticsearch_response_1.json +29 -0
  72. data/spec/elasticsearch_response_2.json +44 -0
  73. data/spec/elasticsearch_top_hits_response.json +20 -0
  74. data/spec/integration_spec.rb +184 -0
  75. data/spec/mapping_spec.rb +219 -0
  76. data/spec/monthly_partitioned_repository_spec.rb +99 -0
  77. data/spec/query_aggregations_spec.rb +44 -0
  78. data/spec/query_conditions_spec.rb +314 -0
  79. data/spec/query_spec.rb +265 -0
  80. data/spec/results_spec.rb +69 -0
  81. data/spec/spec_helper.rb +2 -0
  82. data/spec/term_field_delimiter_spec.rb +39 -0
  83. metadata +225 -0
@@ -0,0 +1,58 @@
1
+ module Elasticated
2
+ module Clonable
3
+
4
+ def clone
5
+ ret = super
6
+ instance_variables.each do |instance_variable|
7
+ value = instance_variable_get instance_variable
8
+ value = case value.class
9
+ when Array
10
+ clone_array value
11
+ when Hash
12
+ Helpers.hash_deep_dup value
13
+ else
14
+ value.clone
15
+ end
16
+ ret.instance_variable_set instance_variable, value
17
+ end
18
+ ret
19
+ end
20
+
21
+ def ==(other_entity)
22
+ other_entity.class == self.class &&
23
+ instance_variables.all? do |instance_variable|
24
+ next true if instance_variable == :@_subaggregations # Subaggregated
25
+ value = instance_variable_get instance_variable
26
+ other_value = other_entity.instance_variable_get instance_variable
27
+ case other_value.class
28
+ when Array
29
+ compare_arrays value, other_value
30
+ else
31
+ other_value == value
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def clone_array(array)
39
+ array.map do |element|
40
+ case element.class
41
+ when Hash
42
+ Helpers.hash_deep_dup element
43
+ when Array
44
+ clone_array element
45
+ else
46
+ element.clone
47
+ end
48
+ end
49
+ end
50
+
51
+ def compare_arrays(array_a, array_b)
52
+ array_a.all? do |element|
53
+ array_b.include? element
54
+ end && array_a.size == array_b.size
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,19 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class CustomCondition
4
+
5
+ include Inspectionable
6
+
7
+ attr_accessor :body
8
+
9
+ def initialize(body)
10
+ self.body = body
11
+ end
12
+
13
+ def build
14
+ body
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class ExistsCondition < StandardCondition
4
+
5
+ def build
6
+ { exists: { field: field }.merge(opts) }
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class MissingCondition < StandardCondition
4
+
5
+ def build
6
+ { missing: { field: field }.merge(opts) }
7
+ end
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class NestedCondition < StandardCondition
4
+
5
+ attr_accessor :inner_conditions
6
+
7
+ def initialize(field, inner_conditions, opts={})
8
+ super(field, opts)
9
+ self.inner_conditions = inner_conditions
10
+ end
11
+
12
+ def build
13
+ body = inner_conditions.build
14
+ { nested: { path: field, filter: body }.merge(opts) }
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class RangeCondition < StandardCondition
4
+
5
+ # example: RangeCondition.new :age, gte: 18, lt: 40
6
+
7
+ attr_accessor :body
8
+
9
+ def initialize(field, body, opts={})
10
+ super(field, opts)
11
+ self.body = Hash::Indifferent.new body
12
+ end
13
+
14
+ def build
15
+ { range: { field => body }.merge(opts) }
16
+ end
17
+
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
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,22 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class ScriptCondition
4
+
5
+ include Inspectionable
6
+
7
+ attr_accessor :script, :params
8
+
9
+ def initialize(script, params={})
10
+ self.script = script
11
+ self.params = params
12
+ end
13
+
14
+ def build
15
+ body = { script: script }
16
+ body.merge! params: params unless params.empty?
17
+ { script: body }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class StandardCondition
4
+
5
+ include Inspectionable
6
+
7
+ include Clonable
8
+
9
+ attr_accessor :field, :opts
10
+
11
+ def initialize(field, opts={})
12
+ self.field = field
13
+ self.opts = opts
14
+ end
15
+
16
+ def fill_date_delimiter(dfd)
17
+ # nothing to do, by default
18
+ end
19
+
20
+ def fill_term_delimiter(tfd)
21
+ # nothing to do, by default
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class TermsCondition < StandardCondition
4
+
5
+ attr_accessor :values
6
+
7
+ def initialize(field, values, opts={})
8
+ super(field, opts)
9
+ self.values = values
10
+ end
11
+
12
+ def build
13
+ { terms: { field => values }.merge(opts) }
14
+ end
15
+
16
+ def fill_delimiter(field_delimiter)
17
+ values.each{ |value| field_delimiter.add_term field, value }
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,18 @@
1
+ module Elasticated
2
+ module Conditions
3
+ class WildcardCondition < StandardCondition
4
+
5
+ attr_accessor :regex
6
+
7
+ def initialize(field, regex, opts={})
8
+ super(field, opts)
9
+ self.regex = regex
10
+ end
11
+
12
+ def build
13
+ { wildcard: { field => regex }.merge(opts) }
14
+ end
15
+
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,75 @@
1
+ module Elasticated
2
+ module ConditionsBuilder
3
+
4
+ include BlockEvaluation
5
+
6
+ def custom(body)
7
+ add Conditions::CustomCondition.new body
8
+ end
9
+
10
+ def equal(field, values, opts={})
11
+ add Conditions::TermsCondition.new field, [*values], opts
12
+ end
13
+ alias_method :terms, :equal
14
+
15
+ def wildcard(field, value, opts={})
16
+ add Conditions::WildcardCondition.new field, value, opts
17
+ end
18
+
19
+ def with(field, opts={})
20
+ add Conditions::WildcardCondition.new field, '*', opts
21
+ end
22
+
23
+ def exists(field, opts={})
24
+ add Conditions::ExistsCondition.new field, opts
25
+ end
26
+
27
+ def missing(field, opts={})
28
+ add Conditions::MissingCondition.new field, opts
29
+ end
30
+
31
+ def between(field, min_value, max_value, opts={})
32
+ add Conditions::RangeCondition.new field, { lte: max_value, gte: min_value }, opts
33
+ end
34
+
35
+ def greater_than(field, value, opts={})
36
+ add Conditions::RangeCondition.new field, { gt: value }, opts
37
+ end
38
+ alias_method :gt, :greater_than
39
+
40
+ def greater_equal(field, value, opts={})
41
+ add Conditions::RangeCondition.new field, { gte: value }, opts
42
+ end
43
+ alias_method :ge, :greater_equal
44
+ alias_method :gte, :greater_equal
45
+
46
+ def less_than(field, value, opts={})
47
+ add Conditions::RangeCondition.new field, { lt: value }, opts
48
+ end
49
+ alias_method :lt, :less_than
50
+
51
+ def less_equal(field, value, opts={})
52
+ add Conditions::RangeCondition.new field, { lte: value }, opts
53
+ end
54
+ alias_method :le, :less_equal
55
+ alias_method :lte, :less_equal
56
+
57
+ def nested(path, opts={}, &block)
58
+ inner_conditions = self.class.new
59
+ inner_conditions.evaluate block
60
+ add Conditions::NestedCondition.new path, inner_conditions, opts
61
+ end
62
+
63
+ def script(script, params={})
64
+ add Conditions::ScriptCondition.new script, params
65
+ end
66
+
67
+ def boolean(&block)
68
+ boolean_children = QueryConditions.new
69
+ boolean_children.evaluate block
70
+ add boolean_children
71
+ end
72
+ alias_method :bool, :boolean
73
+
74
+ end
75
+ end
@@ -0,0 +1,9 @@
1
+ module Elasticated
2
+ module Configurable
3
+
4
+ def log
5
+ Configuration.logger ||= DefaultLogger.new
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Elasticated
2
+ class Configuration
3
+
4
+ class << self
5
+ attr_accessor :logger
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,27 @@
1
+ module Elasticated
2
+ class DefaultLogger
3
+
4
+ # interface
5
+
6
+ def trace(message)
7
+ puts "TRACE #{message}"
8
+ end
9
+
10
+ def debug(message)
11
+ puts "DEBUG #{message}"
12
+ end
13
+
14
+ def info(message)
15
+ puts "INFO #{message}"
16
+ end
17
+
18
+ def warn(message)
19
+ puts "WARN #{message}"
20
+ end
21
+
22
+ def error(message)
23
+ puts "ERROR #{message}"
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ module Elasticated
2
+ module Delimiters
3
+ class DateFieldDelimiter < TermFieldDelimiter
4
+
5
+ attr_accessor :date_since, :date_until
6
+
7
+ def set_minimum(field, date)
8
+ return unless applies_to? field
9
+ self.date_since = date unless date_since && date < date_since
10
+ end
11
+
12
+ def set_maximum(field, date)
13
+ return unless applies_to? field
14
+ self.date_until = date unless date_until && date > date_until
15
+ end
16
+
17
+ def build_strategy_params
18
+ params = Hash.new
19
+ if values.empty?
20
+ raise "date_since is higher than date_until (#{date_since} - #{date_until})" \
21
+ if date_since && date_until && date_since > date_until
22
+ params.merge! date_since: date_since if date_since
23
+ params.merge! date_until: date_until if date_until
24
+ else
25
+ raise "Only one 'term' filter is allowed over the '#{field_name}' field" if values.count > 1
26
+ params.merge! date: values.first
27
+ end
28
+ params
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ module Elasticated
2
+ module Delimiters
3
+ class StandardFieldDelimiter
4
+
5
+ # abstract class
6
+ # child must implement 'build_strategy_params()'
7
+
8
+ attr_accessor :field_name, :filter_name
9
+
10
+ def initialize(opts={})
11
+ self.field_name = opts.fetch :field
12
+ self.filter_name = opts.fetch :as, field_name
13
+ end
14
+
15
+ def applies_to?(condition_field)
16
+ field_name.to_s == condition_field.to_s
17
+ end
18
+
19
+ def add_term(field, value)
20
+ # nothing to do, by default
21
+ end
22
+
23
+ def set_minimum(field, value)
24
+ # nothing to do, by default
25
+ end
26
+
27
+ def set_maximum(field, value)
28
+ # nothing to do, by default
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ module Elasticated
2
+ module Delimiters
3
+ class TermFieldDelimiter < StandardFieldDelimiter
4
+
5
+ attr_accessor :values
6
+
7
+ def initialize(opts={})
8
+ super
9
+ self.values = Array.new
10
+ end
11
+
12
+ def add_term(field, value)
13
+ return unless applies_to? field
14
+ values << value
15
+ end
16
+
17
+ def build_strategy_params
18
+ return Hash.new if values.empty?
19
+ { filter_name => values.uniq }
20
+ end
21
+
22
+ end
23
+ end
24
+ end