elastic-rails 0.5.0 → 0.6.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 +4 -4
- data/lib/elastic/commands/build_agg_from_params.rb +37 -20
- data/lib/elastic/commands/build_query_from_params.rb +109 -79
- data/lib/elastic/commands/build_sort_from_params.rb +41 -0
- data/lib/elastic/commands/import_index_documents.rb +1 -1
- data/lib/elastic/configuration.rb +14 -11
- data/lib/elastic/core/adaptor.rb +0 -1
- data/lib/elastic/core/base_middleware.rb +2 -2
- data/lib/elastic/core/default_middleware.rb +1 -1
- data/lib/elastic/core/definition.rb +53 -34
- data/lib/elastic/core/query_assembler.rb +51 -19
- data/lib/elastic/core/query_config.rb +4 -5
- data/lib/elastic/core/source_formatter.rb +12 -31
- data/lib/elastic/datatypes/date.rb +32 -0
- data/lib/elastic/datatypes/default.rb +74 -0
- data/lib/elastic/datatypes/string.rb +7 -0
- data/lib/elastic/datatypes/term.rb +10 -0
- data/lib/elastic/datatypes/time.rb +29 -0
- data/lib/elastic/dsl/bool_query_builder.rb +4 -0
- data/lib/elastic/fields/nested.rb +24 -6
- data/lib/elastic/fields/value.rb +69 -25
- data/lib/elastic/nested_query.rb +34 -0
- data/lib/elastic/nested_type.rb +10 -0
- data/lib/elastic/nodes/agg/average.rb +3 -1
- data/lib/elastic/nodes/agg/base_metric.rb +6 -5
- data/lib/elastic/nodes/agg/date_histogram.rb +4 -4
- data/lib/elastic/nodes/agg/maximum.rb +3 -1
- data/lib/elastic/nodes/agg/minimum.rb +3 -1
- data/lib/elastic/nodes/agg/stats.rb +3 -1
- data/lib/elastic/nodes/agg/sum.rb +3 -1
- data/lib/elastic/nodes/agg/terms.rb +4 -4
- data/lib/elastic/nodes/agg/top_hits.rb +6 -6
- data/lib/elastic/nodes/and.rb +2 -2
- data/lib/elastic/nodes/base.rb +5 -3
- data/lib/elastic/nodes/base_agg.rb +2 -2
- data/lib/elastic/nodes/boolean.rb +34 -14
- data/lib/elastic/nodes/concerns/aggregable.rb +12 -8
- data/lib/elastic/nodes/concerns/bucketed.rb +4 -7
- data/lib/elastic/nodes/concerns/field_query.rb +10 -0
- data/lib/elastic/nodes/concerns/hit_provider.rb +11 -0
- data/lib/elastic/nodes/function_score.rb +8 -7
- data/lib/elastic/nodes/match.rb +6 -5
- data/lib/elastic/nodes/nested.rb +28 -7
- data/lib/elastic/nodes/range.rb +9 -8
- data/lib/elastic/nodes/search.rb +11 -10
- data/lib/elastic/nodes/sort.rb +82 -0
- data/lib/elastic/nodes/term.rb +7 -6
- data/lib/elastic/query.rb +24 -12
- data/lib/elastic/railtie.rb +7 -0
- data/lib/elastic/railties/ar_helpers.rb +2 -1
- data/lib/elastic/railties/configuration_extensions.rb +13 -0
- data/lib/elastic/railties/indexable_record.rb +1 -2
- data/lib/elastic/railties/indexing_job.rb +8 -0
- data/lib/elastic/railties/type_extensions.rb +1 -1
- data/lib/elastic/results/aggregations.rb +1 -1
- data/lib/elastic/results/bucket.rb +3 -2
- data/lib/elastic/results/grouped_result.rb +31 -1
- data/lib/elastic/results/hit.rb +8 -20
- data/lib/elastic/results/hit_collection.rb +2 -33
- data/lib/elastic/results/root.rb +3 -2
- data/lib/elastic/results/scored_collection.rb +44 -0
- data/lib/elastic/results/scored_item.rb +10 -0
- data/lib/elastic/shims/base.rb +6 -4
- data/lib/elastic/shims/concerns/hit_picker.rb +41 -0
- data/lib/elastic/shims/field_picking.rb +20 -0
- data/lib/elastic/shims/grouping.rb +17 -8
- data/lib/elastic/shims/id_picking.rb +15 -0
- data/lib/elastic/shims/populating.rb +4 -11
- data/lib/elastic/shims/reducing.rb +3 -7
- data/lib/elastic/shims/total_picking.rb +16 -0
- data/lib/elastic/type.rb +6 -3
- data/lib/elastic/types/base_type.rb +16 -9
- data/lib/elastic/types/faceted_type.rb +1 -1
- data/lib/elastic/types/nestable_type.rb +2 -2
- data/lib/elastic/version.rb +1 -1
- data/lib/elastic.rb +15 -0
- data/lib/generators/elastic/index_generator.rb +1 -1
- data/lib/generators/elastic/init_generator.rb +10 -0
- data/lib/generators/elastic/templates/elastic.yml +14 -0
- data/lib/generators/elastic/templates/index.rb +0 -1
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a85d4715234d67d4dac798756ad8c63b62b8aeb2
|
4
|
+
data.tar.gz: fa4bb1a83eae9d73ab8c1ce7717f4232922bd6f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c95fda8f2273c68285ee7bfc02c7f5b01bceccdfef74c3ad2dfa86d8d5cd27420a4c4598c608ba535900c2268030dea3ced38bbed62db35a6b0f037c3630866d
|
7
|
+
data.tar.gz: 1600194a988639918c4810d0bfebf9be14c24c9b9f78eb2ed64b9f64ed8e46ae82c03c2b38d8c563f229f42910c2823284ec8fafd34097ff8bd41f1b77484c10
|
@@ -2,7 +2,8 @@ module Elastic::Commands
|
|
2
2
|
class BuildAggFromParams < Elastic::Support::Command.new(:index, :params)
|
3
3
|
def perform
|
4
4
|
parse_params
|
5
|
-
raise ArgumentError, "field not mapped
|
5
|
+
raise ArgumentError, "#{@field} not mapped" if field_definition.nil?
|
6
|
+
raise ArgumentError, "cant aggregate on #{@field}" if field_definition.nested?
|
6
7
|
|
7
8
|
path = parse_nesting_path
|
8
9
|
raise NotImplementedError, "nested paths not yet supported in aggregations" if path
|
@@ -12,10 +13,6 @@ module Elastic::Commands
|
|
12
13
|
|
13
14
|
private
|
14
15
|
|
15
|
-
def agg_name
|
16
|
-
@options.fetch(:as, @field)
|
17
|
-
end
|
18
|
-
|
19
16
|
def parse_params
|
20
17
|
@field = params[0].to_s
|
21
18
|
@options = params[1] || {}
|
@@ -28,36 +25,56 @@ module Elastic::Commands
|
|
28
25
|
end
|
29
26
|
|
30
27
|
def build_node
|
31
|
-
|
32
|
-
|
28
|
+
agg_type = infer_agg_type
|
29
|
+
raise "aggregation not supported by #{@field}" if agg_type.nil?
|
30
|
+
|
31
|
+
node_options = field_definition.public_send("#{agg_type}_aggregation_defaults")
|
32
|
+
node_options = node_options.merge(@options)
|
33
|
+
send("build_#{agg_type}", node_options)
|
34
|
+
end
|
33
35
|
|
34
|
-
|
36
|
+
def infer_agg_type
|
37
|
+
alternatives = infer_type_options
|
38
|
+
if alternatives.nil?
|
39
|
+
field_definition.supported_aggregations.first
|
40
|
+
else
|
41
|
+
field_definition.supported_aggregations.find { |q| alternatives.include? q }
|
42
|
+
end
|
35
43
|
end
|
36
44
|
|
37
|
-
def
|
38
|
-
return :
|
45
|
+
def infer_type_options
|
46
|
+
return [@options[:type].to_sym] if @options.key? :type
|
47
|
+
return [:range] if @options.key? :ranges
|
48
|
+
return [:histogram, :date_histogram] if @options.key? :interval
|
49
|
+
nil
|
50
|
+
end
|
39
51
|
|
40
|
-
|
41
|
-
|
42
|
-
|
52
|
+
def apply_query_defaults(_agg_type, _options)
|
53
|
+
_definition.default_options_for(query: _query_type).merge(_options)
|
54
|
+
end
|
43
55
|
|
44
|
-
|
56
|
+
def field_definition
|
57
|
+
@field_definition ||= index.definition.get_field @field
|
45
58
|
end
|
46
59
|
|
47
|
-
def build_range
|
60
|
+
def build_range(_options)
|
48
61
|
raise NotImplementedError, 'range aggregation not yet implemented'
|
49
62
|
end
|
50
63
|
|
51
|
-
def build_histogram
|
64
|
+
def build_histogram(_options)
|
52
65
|
raise NotImplementedError, 'histogram aggregation not yet implemented'
|
53
66
|
end
|
54
67
|
|
55
|
-
def build_date_histogram
|
56
|
-
Elastic::Nodes::Agg::DateHistogram.build(agg_name, @field, interval:
|
68
|
+
def build_date_histogram(_options)
|
69
|
+
Elastic::Nodes::Agg::DateHistogram.build(agg_name, @field, interval: _options[:interval])
|
70
|
+
end
|
71
|
+
|
72
|
+
def build_terms(_options)
|
73
|
+
Elastic::Nodes::Agg::Terms.build(agg_name, @field, size: _options[:size])
|
57
74
|
end
|
58
75
|
|
59
|
-
def
|
60
|
-
|
76
|
+
def agg_name
|
77
|
+
@options.fetch(:as, @field)
|
61
78
|
end
|
62
79
|
end
|
63
80
|
end
|
@@ -1,20 +1,10 @@
|
|
1
1
|
module Elastic::Commands
|
2
|
-
class BuildQueryFromParams < Elastic::Support::Command.new(
|
3
|
-
:index, :params, block: nil, prefix: nil
|
4
|
-
)
|
5
|
-
|
2
|
+
class BuildQueryFromParams < Elastic::Support::Command.new(:index, :params, block: nil)
|
6
3
|
def perform
|
7
4
|
if block
|
8
5
|
# TODO: builder mode, support nesting through first parameter
|
9
6
|
else
|
10
|
-
node =
|
11
|
-
Elastic::Nodes::Boolean.build_and(part.map do |field, options|
|
12
|
-
field = field.to_s
|
13
|
-
path = get_nesting_path field
|
14
|
-
query_node = build_query_node(field, options)
|
15
|
-
path.nil? ? query_node : Elastic::Nodes::Nested.build(with_prefix(path), query_node)
|
16
|
-
end)
|
17
|
-
end)
|
7
|
+
node = build_or_node(params)
|
18
8
|
end
|
19
9
|
|
20
10
|
node.simplify
|
@@ -22,111 +12,151 @@ module Elastic::Commands
|
|
22
12
|
|
23
13
|
private
|
24
14
|
|
25
|
-
def
|
26
|
-
|
27
|
-
|
28
|
-
|
15
|
+
def build_or_node(_array)
|
16
|
+
Elastic::Nodes::Boolean.build_or(_array.map do |part|
|
17
|
+
case part
|
18
|
+
when Elastic::Query
|
19
|
+
extract_query_node part
|
20
|
+
when Hash
|
21
|
+
build_and_node part
|
22
|
+
else
|
23
|
+
raise ArgumentError, "expected hash or query but got #{part.class}"
|
24
|
+
end
|
25
|
+
end)
|
29
26
|
end
|
30
27
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
28
|
+
def extract_query_node(_query)
|
29
|
+
raise ArgumentError, "query type mismatch, expected #{index.class}" if _query.index != index
|
30
|
+
_query.as_query_node
|
31
|
+
end
|
34
32
|
|
35
|
-
|
36
|
-
|
33
|
+
def build_and_node(_hash)
|
34
|
+
Elastic::Nodes::Boolean.build_and(_hash.map do |field, options|
|
35
|
+
build_query_node field, options
|
36
|
+
end)
|
37
37
|
end
|
38
38
|
|
39
|
-
def
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
nil
|
39
|
+
def build_query_node(_field, _options)
|
40
|
+
path, field = split_nesting_path(_field.to_s)
|
41
|
+
if path
|
42
|
+
definition = resolve_field_defintion! path
|
43
|
+
raise ArgumentError, "invalid nesting path #{path}" unless definition.nested?
|
44
|
+
build_nested_query(path, definition, field => _options)
|
45
|
+
else
|
46
|
+
build_regular_query(field, _options)
|
47
|
+
end
|
49
48
|
end
|
50
49
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
50
|
+
def split_nesting_path(_field)
|
51
|
+
dot_index = _field.rindex('.')
|
52
|
+
return [nil, _field] if dot_index.nil?
|
53
|
+
[_field[0..dot_index - 1], _field[dot_index + 1..-1]]
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
57
|
-
|
58
|
-
raise ArgumentError, "field not mapped: #{_field}" if properties.nil?
|
56
|
+
def build_regular_query(_field, _options)
|
57
|
+
definition = resolve_field_defintion!(_field)
|
59
58
|
|
60
|
-
|
61
|
-
|
62
|
-
prepare_nested_options _options, properties
|
63
|
-
when 'string'
|
64
|
-
prepare_string_options _options, properties
|
59
|
+
if definition.nested?
|
60
|
+
build_nested_query(_field, definition, _options)
|
65
61
|
else
|
66
|
-
|
62
|
+
query_type = infer_query_type definition, _options
|
63
|
+
raise "query not supported by #{_field}" if query_type.nil?
|
64
|
+
_options = option_to_hash(query_type, _options) unless _options.is_a? Hash
|
65
|
+
_options = definition.public_send("#{query_type}_query_defaults").merge(_options)
|
66
|
+
|
67
|
+
send("build_#{query_type}", definition, _options)
|
67
68
|
end
|
68
69
|
end
|
69
70
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
71
|
+
def resolve_field_defintion!(_path)
|
72
|
+
definition = index.definition.get_field _path
|
73
|
+
raise ArgumentError, "field not mapped: #{_path}" if definition.nil?
|
74
|
+
definition
|
73
75
|
end
|
74
76
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
77
|
+
def infer_query_type(_definition, _options)
|
78
|
+
alternatives = infer_query_type_from_options(_options)
|
79
|
+
if alternatives.nil?
|
80
|
+
_definition.supported_queries.first
|
81
|
+
else
|
82
|
+
_definition.supported_queries.find { |q| alternatives.include? q }
|
83
|
+
end
|
78
84
|
end
|
79
85
|
|
80
|
-
def
|
81
|
-
|
82
|
-
|
83
|
-
|
86
|
+
def build_nested_query(_path, _definition, _query)
|
87
|
+
case _query
|
88
|
+
when Elastic::NestedQuery
|
89
|
+
if _query.index != _definition.index
|
90
|
+
raise ArgumentError,
|
91
|
+
"query type mismatch for #{_path}, expected #{_definition.index.class}"
|
92
|
+
end
|
93
|
+
|
94
|
+
return _query.as_node.tap { |node| node.path = _path }
|
95
|
+
when Hash
|
96
|
+
_query = [_query]
|
97
|
+
end
|
98
|
+
|
99
|
+
nested_node = BuildQueryFromParams.for(index: _definition.index, params: _query)
|
100
|
+
Elastic::Nodes::Nested.build _path, nested_node
|
84
101
|
end
|
85
102
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
103
|
+
def infer_query_type_from_options(_options)
|
104
|
+
case _options
|
105
|
+
when Hash
|
106
|
+
return [_options[:type].to_sym] if _options.key?(:type)
|
107
|
+
return [:term] if _options.key?(:term) || _options.key?(:terms)
|
108
|
+
return [:match] if _options.key? :matches
|
109
|
+
return [:range] if _options.key?(:gte) || _options.key?(:gt)
|
110
|
+
return [:range] if _options.key?(:lte) || _options.key?(:lt)
|
111
|
+
when String, Symbol
|
112
|
+
return [:term, :match]
|
113
|
+
when Array
|
114
|
+
return [:term]
|
115
|
+
when Range
|
116
|
+
return [:range]
|
117
|
+
end
|
118
|
+
|
119
|
+
nil
|
120
|
+
end
|
89
121
|
|
90
|
-
|
91
|
-
|
122
|
+
def option_to_hash(_query_type, _value)
|
123
|
+
case _query_type
|
124
|
+
when :term
|
125
|
+
{ terms: _value }
|
126
|
+
when :match
|
127
|
+
{ matches: _value.to_s }
|
128
|
+
when :range
|
129
|
+
{ gte: _value.begin, (_value.exclude_end? ? :lt : :lte) => _value.end }
|
130
|
+
end
|
92
131
|
end
|
93
132
|
|
133
|
+
# NOTE: the following methods could be placed in separate factories.
|
134
|
+
|
94
135
|
def build_term(_field, _options)
|
95
|
-
terms = Array(_options
|
136
|
+
terms = Array(_options.fetch(:term, _options[:terms]))
|
96
137
|
|
97
138
|
Elastic::Nodes::Term.new.tap do |node|
|
98
|
-
node.field = _field
|
139
|
+
node.field = _field.name
|
99
140
|
node.mode = _options[:mode]
|
100
|
-
node.terms = terms.map { |t|
|
141
|
+
node.terms = terms.map { |t| _field.prepare_value_for_query(t) }
|
101
142
|
end
|
102
143
|
end
|
103
144
|
|
104
145
|
def build_range(_field, _options)
|
105
146
|
Elastic::Nodes::Range.new.tap do |node|
|
106
|
-
node.field = _field
|
107
|
-
node.gte =
|
108
|
-
node.gt =
|
109
|
-
node.lte =
|
110
|
-
node.lt =
|
147
|
+
node.field = _field.name
|
148
|
+
node.gte = _field.prepare_value_for_query(_options[:gte]) if _options.key? :gte
|
149
|
+
node.gt = _field.prepare_value_for_query(_options[:gt]) if _options.key? :gt
|
150
|
+
node.lte = _field.prepare_value_for_query(_options[:lte]) if _options.key? :lte
|
151
|
+
node.lt = _field.prepare_value_for_query(_options[:lt]) if _options.key? :lt
|
111
152
|
end
|
112
153
|
end
|
113
154
|
|
114
155
|
def build_match(_field, _options)
|
115
156
|
Elastic::Nodes::Match.new.tap do |node|
|
116
|
-
node.field = _field
|
117
|
-
node.query =
|
157
|
+
node.field = _field.name
|
158
|
+
node.query = _field.prepare_value_for_query(_options[:matches])
|
118
159
|
end
|
119
160
|
end
|
120
|
-
|
121
|
-
def range_to_options(_range)
|
122
|
-
{
|
123
|
-
gte: _range.begin,
|
124
|
-
(_range.exclude_end? ? :lt : :lte) => _range.end
|
125
|
-
}
|
126
|
-
end
|
127
|
-
|
128
|
-
def prep(_field, _value)
|
129
|
-
index.definition.get_field(_field).prepare_value_for_query(_value)
|
130
|
-
end
|
131
161
|
end
|
132
162
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Elastic::Commands
|
2
|
+
class BuildSortFromParams < Elastic::Support::Command.new(:index, :params)
|
3
|
+
def perform
|
4
|
+
params.each do |param|
|
5
|
+
case param
|
6
|
+
when Hash
|
7
|
+
param.each { |field, options| add_sort field, options }
|
8
|
+
else
|
9
|
+
add_sort param
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
node.add_score_sort
|
14
|
+
node
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def node
|
20
|
+
@node ||= Elastic::Nodes::Sort.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_sort(_field, _options = {})
|
24
|
+
_field = _field.to_s
|
25
|
+
_options = { order: _options } unless _options.is_a? Hash
|
26
|
+
|
27
|
+
raise ArgumentError, "field not mapped: #{_field}" unless index.definition.has_field? _field
|
28
|
+
|
29
|
+
path = parse_nesting_path(_field)
|
30
|
+
raise NotImplementedError, "nested fields not yet supported in sorting" if path
|
31
|
+
|
32
|
+
node.add_sort(_field, _options)
|
33
|
+
end
|
34
|
+
|
35
|
+
def parse_nesting_path(_field)
|
36
|
+
dot_index = _field.rindex('.')
|
37
|
+
return nil if dot_index.nil?
|
38
|
+
_field.slice(0, dot_index)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -14,7 +14,7 @@ module Elastic::Commands
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def import_collection
|
17
|
-
main_target.
|
17
|
+
main_target.collect_from(collection, middleware_options) { |obj| queue obj }
|
18
18
|
end
|
19
19
|
|
20
20
|
def import_target(_target)
|
@@ -1,13 +1,26 @@
|
|
1
1
|
module Elastic
|
2
2
|
module Configuration
|
3
|
+
DEFAULT = {
|
4
|
+
host: '127.0.0.1',
|
5
|
+
port: 9200,
|
6
|
+
page_size: 20,
|
7
|
+
coord_similarity: true
|
8
|
+
}
|
9
|
+
|
3
10
|
extend self
|
4
11
|
|
12
|
+
def reset
|
13
|
+
@config = nil
|
14
|
+
self
|
15
|
+
end
|
16
|
+
|
5
17
|
def configure(_options = nil, &_block)
|
6
18
|
if _options.nil?
|
7
19
|
_block.call self
|
8
20
|
else
|
9
21
|
@config = config.merge _options.symbolize_keys
|
10
22
|
end
|
23
|
+
self
|
11
24
|
end
|
12
25
|
|
13
26
|
def api_client
|
@@ -30,10 +43,6 @@ module Elastic
|
|
30
43
|
@config[:coord_similarity]
|
31
44
|
end
|
32
45
|
|
33
|
-
def strict_mode
|
34
|
-
@config[:strict_types]
|
35
|
-
end
|
36
|
-
|
37
46
|
def logger
|
38
47
|
@config[:logger] || default_logger
|
39
48
|
end
|
@@ -41,13 +50,7 @@ module Elastic
|
|
41
50
|
private
|
42
51
|
|
43
52
|
def config
|
44
|
-
@config ||=
|
45
|
-
host: '127.0.0.1',
|
46
|
-
port: 9200,
|
47
|
-
page_size: 20,
|
48
|
-
coord_similarity: true,
|
49
|
-
strict_types: true
|
50
|
-
}
|
53
|
+
@config ||= DEFAULT
|
51
54
|
end
|
52
55
|
|
53
56
|
def default_logger
|
data/lib/elastic/core/adaptor.rb
CHANGED
@@ -22,8 +22,8 @@ module Elastic::Core
|
|
22
22
|
not_supported :collect_all
|
23
23
|
end
|
24
24
|
|
25
|
-
def
|
26
|
-
not_supported :
|
25
|
+
def collect_from(_collection, _options, &_block)
|
26
|
+
not_supported :collect_from
|
27
27
|
end
|
28
28
|
|
29
29
|
def find_by_ids(_ids, _options)
|
@@ -18,7 +18,7 @@ module Elastic::Core
|
|
18
18
|
target.public_send(method, &_block) if method
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def collect_from(_collection, _options, &_block)
|
22
22
|
method = collect_method_for(_collection)
|
23
23
|
raise ArgumentError, "Could not find a method to iterate over collection" if method.nil?
|
24
24
|
_collection.public_send(method, &_block)
|
@@ -7,11 +7,11 @@ module Elastic::Core
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def targets
|
10
|
-
@target_cache
|
10
|
+
raise 'attempting to access targets before definition has been frozen' if @target_cache.nil?
|
11
|
+
@target_cache
|
11
12
|
end
|
12
13
|
|
13
14
|
def targets=(_values)
|
14
|
-
@target_cache = nil
|
15
15
|
@targets = _values
|
16
16
|
end
|
17
17
|
|
@@ -26,12 +26,11 @@ module Elastic::Core
|
|
26
26
|
def initialize
|
27
27
|
@targets = []
|
28
28
|
@field_map = {}
|
29
|
-
@
|
29
|
+
@field_cache = {}
|
30
30
|
@middleware_options = HashWithIndifferentAccess.new
|
31
31
|
end
|
32
32
|
|
33
33
|
def register_field(_field)
|
34
|
-
raise 'definition has been frozen' if @frozen
|
35
34
|
@field_map[_field.name] = _field
|
36
35
|
end
|
37
36
|
|
@@ -40,59 +39,60 @@ module Elastic::Core
|
|
40
39
|
end
|
41
40
|
|
42
41
|
def expanded_field_names
|
43
|
-
@
|
42
|
+
@field_map.map { |_, field| field.expanded_names }.flatten
|
43
|
+
end
|
44
|
+
|
45
|
+
def freeze
|
46
|
+
return if frozen?
|
47
|
+
cache_targets
|
48
|
+
complete_and_validate_fields
|
49
|
+
freeze_fields
|
50
|
+
@middleware_options.freeze
|
51
|
+
super
|
44
52
|
end
|
45
53
|
|
46
54
|
def get_field(_name)
|
55
|
+
ensure_frozen!
|
56
|
+
|
47
57
|
_name = _name.to_s
|
48
|
-
|
49
|
-
|
50
|
-
@field_map[_name]
|
51
|
-
else
|
52
|
-
parent = @field_map[_name[0...separator]]
|
53
|
-
parent.try(:get_field, _name[separator + 1..-1])
|
54
|
-
end
|
58
|
+
@field_cache[_name] = resolve_field(_name) unless @field_cache.key? _name
|
59
|
+
@field_cache[_name]
|
55
60
|
end
|
56
61
|
|
57
62
|
def has_field?(_name)
|
63
|
+
ensure_frozen!
|
64
|
+
|
58
65
|
!get_field(_name).nil?
|
59
66
|
end
|
60
67
|
|
61
68
|
def as_es_mapping
|
62
|
-
|
69
|
+
ensure_frozen!
|
70
|
+
|
63
71
|
properties = {}
|
64
72
|
@field_map.each_value do |field|
|
65
|
-
|
66
|
-
|
67
|
-
if !field_def.key?(:type) && field.mapping_inference_enabled?
|
68
|
-
inferred = infer_mapping_options(field.name)
|
69
|
-
field_def.merge! inferred.symbolize_keys unless inferred.nil?
|
70
|
-
end
|
71
|
-
|
72
|
-
if Elastic::Configuration.strict_mode && !field_def.key?(:type)
|
73
|
-
raise "explicit field type for #{field.name} required"
|
74
|
-
end
|
75
|
-
|
76
|
-
properties[field.name] = field_def if field_def.key? :type
|
73
|
+
properties[field.name] = field.mapping_options
|
77
74
|
end
|
78
75
|
|
79
76
|
{ 'properties' => properties.as_json }
|
80
77
|
end
|
81
78
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
79
|
+
private
|
80
|
+
|
81
|
+
def resolve_field(_name)
|
82
|
+
separator = _name.index '.'
|
83
|
+
if separator.nil?
|
84
|
+
@field_map[_name]
|
85
|
+
else
|
86
|
+
parent = @field_map[_name[0...separator]]
|
87
|
+
return nil if parent.nil?
|
88
|
+
parent.get_field(_name[separator + 1..-1])
|
87
89
|
end
|
88
90
|
end
|
89
91
|
|
90
|
-
def
|
91
|
-
|
92
|
+
def cache_targets
|
93
|
+
@target_cache = load_targets.freeze
|
92
94
|
end
|
93
95
|
|
94
|
-
private
|
95
|
-
|
96
96
|
def load_targets
|
97
97
|
mode = nil
|
98
98
|
@targets.map do |target|
|
@@ -107,6 +107,25 @@ module Elastic::Core
|
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
|
+
def complete_and_validate_fields
|
111
|
+
@field_map.each_value do |field|
|
112
|
+
field.merge! infer_mapping_options(field.name) if field.needs_inference?
|
113
|
+
|
114
|
+
error = field.validate
|
115
|
+
raise error unless error.nil?
|
116
|
+
end
|
117
|
+
|
118
|
+
@field_map.freeze
|
119
|
+
end
|
120
|
+
|
121
|
+
def ensure_frozen!
|
122
|
+
raise 'definition needs to be frozen' unless frozen?
|
123
|
+
end
|
124
|
+
|
125
|
+
def freeze_fields
|
126
|
+
@field_map.each_value(&:freeze)
|
127
|
+
end
|
128
|
+
|
110
129
|
def load_target_middleware(_target)
|
111
130
|
Middleware.wrap(_target)
|
112
131
|
end
|