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.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/Gemfile +4 -0
- data/README.md +3 -0
- data/Rakefile +6 -0
- data/elasticated.gemspec +29 -0
- data/lib/elasticated.rb +102 -0
- data/lib/elasticated/aggregation.rb +36 -0
- data/lib/elasticated/aggregations/cardinality_aggregation.rb +15 -0
- data/lib/elasticated/aggregations/count_aggregation.rb +15 -0
- data/lib/elasticated/aggregations/count_distinct_aggregation.rb +15 -0
- data/lib/elasticated/aggregations/count_filtered_aggregation.rb +29 -0
- data/lib/elasticated/aggregations/custom_aggregation.rb +25 -0
- data/lib/elasticated/aggregations/date_histogram_aggregation.rb +35 -0
- data/lib/elasticated/aggregations/filter_aggregation.rb +33 -0
- data/lib/elasticated/aggregations/filter_aggregation_evaluator.rb +22 -0
- data/lib/elasticated/aggregations/group_aggregation.rb +29 -0
- data/lib/elasticated/aggregations/histogram_aggregation.rb +34 -0
- data/lib/elasticated/aggregations/nested_aggregation.rb +30 -0
- data/lib/elasticated/aggregations/range_aggregation.rb +35 -0
- data/lib/elasticated/aggregations/range_aggregation_evaluator.rb +22 -0
- data/lib/elasticated/aggregations/ranges_builder.rb +35 -0
- data/lib/elasticated/aggregations/single_value_aggregation.rb +47 -0
- data/lib/elasticated/aggregations/subaggregated.rb +27 -0
- data/lib/elasticated/aggregations/sum_distinct_aggregation.rb +20 -0
- data/lib/elasticated/aggregations/terms_aggregation.rb +63 -0
- data/lib/elasticated/aggregations/top_hits_aggregation.rb +25 -0
- data/lib/elasticated/block_evaluation.rb +15 -0
- data/lib/elasticated/boolean_clause.rb +43 -0
- data/lib/elasticated/client.rb +84 -0
- data/lib/elasticated/clonable.rb +58 -0
- data/lib/elasticated/conditions/custom_condition.rb +19 -0
- data/lib/elasticated/conditions/exists_condition.rb +11 -0
- data/lib/elasticated/conditions/missing_condition.rb +11 -0
- data/lib/elasticated/conditions/nested_condition.rb +19 -0
- data/lib/elasticated/conditions/range_condition.rb +27 -0
- data/lib/elasticated/conditions/script_condition.rb +22 -0
- data/lib/elasticated/conditions/standard_condition.rb +26 -0
- data/lib/elasticated/conditions/terms_condition.rb +22 -0
- data/lib/elasticated/conditions/wildcard_condition.rb +18 -0
- data/lib/elasticated/conditions_builder.rb +75 -0
- data/lib/elasticated/configurable.rb +9 -0
- data/lib/elasticated/configuration.rb +9 -0
- data/lib/elasticated/default_logger.rb +27 -0
- data/lib/elasticated/delimiters/date_field_delimiter.rb +33 -0
- data/lib/elasticated/delimiters/standard_field_delimiter.rb +33 -0
- data/lib/elasticated/delimiters/term_field_delimiter.rb +24 -0
- data/lib/elasticated/document.rb +46 -0
- data/lib/elasticated/helpers.rb +28 -0
- data/lib/elasticated/index_selector.rb +44 -0
- data/lib/elasticated/inspectionable.rb +9 -0
- data/lib/elasticated/mapping.rb +19 -0
- data/lib/elasticated/mapping/builder.rb +36 -0
- data/lib/elasticated/mapping/fields_builder.rb +148 -0
- data/lib/elasticated/mapping/nested_builder.rb +15 -0
- data/lib/elasticated/mapping/object_builder.rb +15 -0
- data/lib/elasticated/mapping/partial.rb +11 -0
- data/lib/elasticated/mapping/type_builder.rb +14 -0
- data/lib/elasticated/partitioned_repository.rb +27 -0
- data/lib/elasticated/query.rb +159 -0
- data/lib/elasticated/query_aggregations.rb +71 -0
- data/lib/elasticated/query_conditions.rb +89 -0
- data/lib/elasticated/repositories/monthly_partitioned_repository.rb +96 -0
- data/lib/elasticated/repository.rb +139 -0
- data/lib/elasticated/results.rb +43 -0
- data/lib/version.rb +92 -0
- data/spec/aggregation_spec.rb +587 -0
- data/spec/date_field_delimiter_spec.rb +67 -0
- data/spec/document_spec.rb +44 -0
- data/spec/elasticsearch_hit_1.json +14 -0
- data/spec/elasticsearch_response_1.json +29 -0
- data/spec/elasticsearch_response_2.json +44 -0
- data/spec/elasticsearch_top_hits_response.json +20 -0
- data/spec/integration_spec.rb +184 -0
- data/spec/mapping_spec.rb +219 -0
- data/spec/monthly_partitioned_repository_spec.rb +99 -0
- data/spec/query_aggregations_spec.rb +44 -0
- data/spec/query_conditions_spec.rb +314 -0
- data/spec/query_spec.rb +265 -0
- data/spec/results_spec.rb +69 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/term_field_delimiter_spec.rb +39 -0
- 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 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,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
|