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
@@ -20,11 +20,11 @@ module Elastic::Nodes::Agg
|
|
20
20
|
prepare_clone(super)
|
21
21
|
end
|
22
22
|
|
23
|
-
def render
|
24
|
-
|
25
|
-
|
23
|
+
def render(_options = {})
|
24
|
+
hash = { 'field' => @field.to_s }
|
25
|
+
hash['size'] = @size if @size
|
26
26
|
|
27
|
-
render_aggs 'terms' =>
|
27
|
+
render_aggs({ 'terms' => hash }, _options)
|
28
28
|
end
|
29
29
|
|
30
30
|
private
|
@@ -2,15 +2,15 @@ module Elastic::Nodes
|
|
2
2
|
class TopHits < BaseAgg
|
3
3
|
include Concerns::HitProvider
|
4
4
|
|
5
|
-
def render
|
6
|
-
|
7
|
-
render_hit_options
|
5
|
+
def render(_options = {})
|
6
|
+
hash = {}
|
7
|
+
render_hit_options hash
|
8
8
|
|
9
|
-
{ 'top_hits' =>
|
9
|
+
{ 'top_hits' => hash }
|
10
10
|
end
|
11
11
|
|
12
|
-
def handle_result(_raw)
|
13
|
-
hits = _raw['hits'] ? _raw['hits']['hits']
|
12
|
+
def handle_result(_raw, _formatter)
|
13
|
+
hits = _raw['hits'] ? prepare_hits(_raw['hits']['hits'], _formatter) : []
|
14
14
|
Elastic::Results::HitCollection.new(hits)
|
15
15
|
end
|
16
16
|
end
|
data/lib/elastic/nodes/and.rb
CHANGED
data/lib/elastic/nodes/base.rb
CHANGED
@@ -10,7 +10,7 @@ module Elastic::Nodes
|
|
10
10
|
_block.call(self)
|
11
11
|
end
|
12
12
|
|
13
|
-
def render
|
13
|
+
def render(_options = {})
|
14
14
|
raise NotImplementedError, 'render must be implemented by each node'
|
15
15
|
end
|
16
16
|
|
@@ -22,8 +22,8 @@ module Elastic::Nodes
|
|
22
22
|
self.class.new
|
23
23
|
end
|
24
24
|
|
25
|
-
def handle_result(_raw)
|
26
|
-
|
25
|
+
def handle_result(_raw, _formatter)
|
26
|
+
_raw
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -32,3 +32,5 @@ require "elastic/nodes/concerns/hit_provider"
|
|
32
32
|
require "elastic/nodes/concerns/aggregable"
|
33
33
|
require "elastic/nodes/concerns/bucketed"
|
34
34
|
require "elastic/nodes/concerns/boostable"
|
35
|
+
require "elastic/nodes/concerns/field_query"
|
36
|
+
|
@@ -16,6 +16,8 @@ module Elastic::Nodes
|
|
16
16
|
super
|
17
17
|
@musts = []
|
18
18
|
@shoulds = []
|
19
|
+
@filters = []
|
20
|
+
@disable_coord = !Elastic::Configuration.coord_similarity
|
19
21
|
end
|
20
22
|
|
21
23
|
def must(_node)
|
@@ -26,6 +28,10 @@ module Elastic::Nodes
|
|
26
28
|
@shoulds << _node
|
27
29
|
end
|
28
30
|
|
31
|
+
def filter(_node)
|
32
|
+
@filters << _node
|
33
|
+
end
|
34
|
+
|
29
35
|
def musts=(_nodes)
|
30
36
|
@musts = _nodes.dup.to_a
|
31
37
|
end
|
@@ -42,43 +48,57 @@ module Elastic::Nodes
|
|
42
48
|
@shoulds.each
|
43
49
|
end
|
44
50
|
|
51
|
+
def filters=(_nodes)
|
52
|
+
@filters = _nodes.dup.to_a
|
53
|
+
end
|
54
|
+
|
55
|
+
def filters
|
56
|
+
@filters.each
|
57
|
+
end
|
58
|
+
|
45
59
|
def traverse(&_block)
|
46
60
|
super
|
47
61
|
@shoulds.each { |c| c.traverse(&_block) }
|
48
62
|
@musts.each { |c| c.traverse(&_block) }
|
49
63
|
end
|
50
64
|
|
51
|
-
def render
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
65
|
+
def render(_options = {})
|
66
|
+
hash = {}
|
67
|
+
hash['must'] = @musts.map { |n| n.render(_options) } if !@musts.empty?
|
68
|
+
hash['should'] = @shoulds.map { |n| n.render(_options) } if !@shoulds.empty?
|
69
|
+
hash['filters'] = @filters.map { |n| n.render(_options) } if !@filters.empty?
|
70
|
+
hash['minimum_should_match'] = minimum_should_match unless minimum_should_match.nil?
|
71
|
+
hash['disable_coord'] = true if disable_coord
|
72
|
+
render_boost(hash)
|
59
73
|
|
60
|
-
{ "bool" =>
|
74
|
+
{ "bool" => hash }
|
61
75
|
end
|
62
76
|
|
63
77
|
def clone
|
64
|
-
prepare_clone super, @musts.map(&:clone), @shoulds.map(&:clone)
|
78
|
+
prepare_clone super, @musts.map(&:clone), @shoulds.map(&:clone), @filters.map(&:clone)
|
65
79
|
end
|
66
80
|
|
67
81
|
def simplify
|
68
82
|
new_must = @musts.map(&:simplify)
|
69
83
|
new_should = @shoulds.map(&:simplify)
|
84
|
+
new_filter = @filters.map(&:simplify)
|
70
85
|
|
71
|
-
|
72
|
-
|
86
|
+
# TODO: detect must elements with boost = 0 and move them to "filter"
|
87
|
+
|
88
|
+
if boost.nil? && (new_must.length + new_should.length + new_filter.length) == 1
|
89
|
+
return new_must.first unless new_must.empty?
|
90
|
+
return new_should.first unless new_should.empty? # at least 1 should match
|
91
|
+
end
|
73
92
|
|
74
|
-
prepare_clone(super, new_must, new_should)
|
93
|
+
prepare_clone(super, new_must, new_should, new_filter)
|
75
94
|
end
|
76
95
|
|
77
96
|
private
|
78
97
|
|
79
|
-
def prepare_clone(_clone, _musts, _shoulds)
|
98
|
+
def prepare_clone(_clone, _musts, _shoulds, _filters)
|
80
99
|
_clone.musts = _musts
|
81
100
|
_clone.shoulds = _shoulds
|
101
|
+
_clone.filters = _filters
|
82
102
|
_clone.minimum_should_match = @minimum_should_match
|
83
103
|
_clone.disable_coord = @disable_coord
|
84
104
|
_clone
|
@@ -1,13 +1,17 @@
|
|
1
1
|
module Elastic::Nodes::Concerns
|
2
2
|
module Aggregable
|
3
|
-
def
|
3
|
+
def has_aggregations?
|
4
4
|
aggs.count > 0
|
5
5
|
end
|
6
6
|
|
7
|
-
def
|
7
|
+
def aggregations=(_aggs)
|
8
8
|
@aggs = _aggs.dup.to_a
|
9
9
|
end
|
10
10
|
|
11
|
+
def aggregations
|
12
|
+
@aggs.each
|
13
|
+
end
|
14
|
+
|
11
15
|
def aggregate(_node)
|
12
16
|
raise ArgumentError, 'node must provide a name' unless _node.name
|
13
17
|
aggs << _node
|
@@ -20,13 +24,13 @@ module Elastic::Nodes::Concerns
|
|
20
24
|
|
21
25
|
def clone
|
22
26
|
node = super
|
23
|
-
node.
|
27
|
+
node.aggregations = aggs.map(&:clone)
|
24
28
|
node
|
25
29
|
end
|
26
30
|
|
27
31
|
def simplify
|
28
32
|
node = super
|
29
|
-
node.
|
33
|
+
node.aggregations = aggs.map(&:simplify)
|
30
34
|
node
|
31
35
|
end
|
32
36
|
|
@@ -36,15 +40,15 @@ module Elastic::Nodes::Concerns
|
|
36
40
|
@aggs ||= []
|
37
41
|
end
|
38
42
|
|
39
|
-
def render_aggs(_into)
|
40
|
-
_into['aggs'] = Hash[aggs.map { |a| [a.name, a.render] }] if
|
43
|
+
def render_aggs(_into, _options)
|
44
|
+
_into['aggs'] = Hash[aggs.map { |a| [a.name.to_s, a.render(_options)] }] if has_aggregations?
|
41
45
|
_into
|
42
46
|
end
|
43
47
|
|
44
|
-
def load_aggs_results(_raw)
|
48
|
+
def load_aggs_results(_raw, _formatter)
|
45
49
|
{}.tap do |result|
|
46
50
|
aggs.each do |node|
|
47
|
-
result[node.name] = node.handle_result(_raw[node.name])
|
51
|
+
result[node.name] = node.handle_result(_raw[node.name.to_s], _formatter)
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -1,14 +1,11 @@
|
|
1
1
|
module Elastic::Nodes::Concerns
|
2
2
|
module Bucketed
|
3
|
-
def handle_result(_raw)
|
3
|
+
def handle_result(_raw, _formatter)
|
4
4
|
buckets = _raw['buckets'].map do |raw_bucket|
|
5
|
-
|
5
|
+
key = _formatter.format_field(field, raw_bucket['key'])
|
6
|
+
aggs = load_aggs_results(raw_bucket, _formatter)
|
6
7
|
|
7
|
-
|
8
|
-
# configured that way
|
9
|
-
# return Elastic::Results::SimpleBucket.new(raw_bucket['key'], aggs.first) if blebliblu
|
10
|
-
|
11
|
-
Elastic::Results::Bucket.new(raw_bucket['key'], aggs)
|
8
|
+
Elastic::Results::Bucket.new(key, raw_bucket['doc_count'], aggs)
|
12
9
|
end
|
13
10
|
|
14
11
|
Elastic::Results::BucketCollection.new buckets
|
@@ -24,6 +24,17 @@ module Elastic::Nodes::Concerns
|
|
24
24
|
|
25
25
|
private
|
26
26
|
|
27
|
+
def prepare_hits(_hits, _formatter)
|
28
|
+
_hits.map do |raw_hit|
|
29
|
+
Elastic::Results::Hit.new(
|
30
|
+
raw_hit['_type'],
|
31
|
+
raw_hit['_id'],
|
32
|
+
raw_hit['_score'],
|
33
|
+
raw_hit['_source'] ? _formatter.format(raw_hit['_source']) : nil
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
27
38
|
def copy_hit_options(_clone)
|
28
39
|
_clone.size = @size
|
29
40
|
_clone.source = @source
|
@@ -54,18 +54,19 @@ module Elastic::Nodes
|
|
54
54
|
@query.traverse(&_block)
|
55
55
|
end
|
56
56
|
|
57
|
-
def render
|
58
|
-
|
59
|
-
|
57
|
+
def render(_options = {})
|
58
|
+
hash = { 'query' => @query.render(_options) }
|
59
|
+
hash['boost_mode'] = @boost_mode.to_s if @boost_mode && @boost_mode != :multiply
|
60
60
|
|
61
|
+
# TODO: add support for the query_path option
|
61
62
|
if @functions.length > 1
|
62
|
-
|
63
|
-
|
63
|
+
hash['score_mode'] = @score_mode.to_s if @score_mode && @score_mode != :multiply
|
64
|
+
hash['functions'] = @functions
|
64
65
|
elsif @functions.length == 1
|
65
|
-
|
66
|
+
hash.merge! @functions.first
|
66
67
|
end
|
67
68
|
|
68
|
-
{ 'function_score' => render_boost(
|
69
|
+
{ 'function_score' => render_boost(hash) }
|
69
70
|
end
|
70
71
|
|
71
72
|
alias :super_clone :clone
|
data/lib/elastic/nodes/match.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
module Elastic::Nodes
|
2
2
|
class Match < Base
|
3
3
|
include Concerns::Boostable
|
4
|
+
include Concerns::FieldQuery
|
4
5
|
|
5
6
|
MATCH_MODES = [:boolean, :phrase, :phrase_prefix]
|
6
7
|
|
7
|
-
attr_accessor :
|
8
|
+
attr_accessor :query
|
8
9
|
attr_reader :mode
|
9
10
|
|
10
11
|
def query=(_query)
|
@@ -26,11 +27,11 @@ module Elastic::Nodes
|
|
26
27
|
prepare_clone(super)
|
27
28
|
end
|
28
29
|
|
29
|
-
def render
|
30
|
-
|
31
|
-
|
30
|
+
def render(_options = {})
|
31
|
+
hash = { 'query' => @query }
|
32
|
+
hash['type'] = @mode.to_s unless @mode.nil? || @mode == :boolean
|
32
33
|
|
33
|
-
{ "match" => {
|
34
|
+
{ "match" => { render_field(_options) => render_boost(hash) } }
|
34
35
|
end
|
35
36
|
|
36
37
|
private
|
data/lib/elastic/nodes/nested.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
module Elastic::Nodes
|
2
2
|
class Nested < Base
|
3
|
+
SCORE_MODES = [:avg, :sum, :min, :max, :none]
|
4
|
+
|
3
5
|
def self.build(_path, _child)
|
4
6
|
new.tap do |node|
|
5
7
|
node.path = _path
|
@@ -8,6 +10,7 @@ module Elastic::Nodes
|
|
8
10
|
end
|
9
11
|
|
10
12
|
attr_accessor :path, :child
|
13
|
+
attr_reader :score_mode
|
11
14
|
|
12
15
|
def traverse(&_block)
|
13
16
|
super
|
@@ -18,17 +21,34 @@ module Elastic::Nodes
|
|
18
21
|
prepare_clone super, @child.clone
|
19
22
|
end
|
20
23
|
|
24
|
+
def score_mode=(_value)
|
25
|
+
raise ArgumentError, "invalid score mode #{_value}" if _value && !SCORE_MODES.include?(_value)
|
26
|
+
@score_mode = _value
|
27
|
+
end
|
28
|
+
|
21
29
|
def simplify
|
22
|
-
|
30
|
+
new_child = @child.simplify
|
31
|
+
if new_child.is_a? Nested
|
32
|
+
prepare_clone(super, new_child.child).tap do |clone|
|
33
|
+
clone.path = "#{clone.path}.#{new_child.path}"
|
34
|
+
end
|
35
|
+
else
|
36
|
+
prepare_clone super, new_child
|
37
|
+
end
|
23
38
|
end
|
24
39
|
|
25
|
-
def render
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
40
|
+
def render(_options = {})
|
41
|
+
path = @path
|
42
|
+
path = "#{_options[:query_path]}.#{path}" if _options.key? :query_path
|
43
|
+
|
44
|
+
hash = {
|
45
|
+
'path' => path,
|
46
|
+
'query' => @child.render(_options.merge(query_path: path))
|
31
47
|
}
|
48
|
+
|
49
|
+
hash['score_mode'] = @score_mode.to_s if @score_mode && @score_mode != :avg
|
50
|
+
|
51
|
+
{ "nested" => hash }
|
32
52
|
end
|
33
53
|
|
34
54
|
private
|
@@ -36,6 +56,7 @@ module Elastic::Nodes
|
|
36
56
|
def prepare_clone(_clone, _child)
|
37
57
|
_clone.path = @path
|
38
58
|
_clone.child = _child
|
59
|
+
_clone.score_mode = @score_mode
|
39
60
|
_clone
|
40
61
|
end
|
41
62
|
end
|
data/lib/elastic/nodes/range.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
module Elastic::Nodes
|
2
2
|
class Range < Base
|
3
3
|
include Concerns::Boostable
|
4
|
+
include Concerns::FieldQuery
|
4
5
|
|
5
|
-
attr_accessor :
|
6
|
+
attr_accessor :gte, :gt, :lte, :lt
|
6
7
|
|
7
8
|
def clone
|
8
9
|
prepare_clone(super)
|
@@ -12,14 +13,14 @@ module Elastic::Nodes
|
|
12
13
|
prepare_clone(super)
|
13
14
|
end
|
14
15
|
|
15
|
-
def render
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
16
|
+
def render(_options = {})
|
17
|
+
hash = {}
|
18
|
+
hash['gte'] = @gte unless @gte.nil?
|
19
|
+
hash['gt'] = @gt unless @gt.nil?
|
20
|
+
hash['lte'] = @lte unless @lte.nil?
|
21
|
+
hash['lt'] = @lt unless @lt.nil?
|
21
22
|
|
22
|
-
{ "range" => {
|
23
|
+
{ "range" => { render_field(_options) => render_boost(hash) } }
|
23
24
|
end
|
24
25
|
|
25
26
|
private
|
data/lib/elastic/nodes/search.rb
CHANGED
@@ -14,11 +14,11 @@ module Elastic::Nodes
|
|
14
14
|
@query.traverse(&_block)
|
15
15
|
end
|
16
16
|
|
17
|
-
def render
|
18
|
-
{ "query" => @query.render }.tap do |
|
19
|
-
|
20
|
-
render_hit_options(
|
21
|
-
render_aggs(
|
17
|
+
def render(_options = {})
|
18
|
+
{ "query" => @query.render(_options) }.tap do |hash|
|
19
|
+
hash["from"] = @offset if offset && offset > 0
|
20
|
+
render_hit_options(hash)
|
21
|
+
render_aggs(hash, _options)
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -30,11 +30,12 @@ module Elastic::Nodes
|
|
30
30
|
prepare_clone(super, @query.simplify)
|
31
31
|
end
|
32
32
|
|
33
|
-
def handle_result(_raw)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
def handle_result(_raw, _formatter)
|
34
|
+
Elastic::Results::Root.new(
|
35
|
+
_raw['hits'] ? prepare_hits(_raw['hits']['hits'], _formatter) : [],
|
36
|
+
_raw['hits'] ? _raw['hits']['total'] : 0,
|
37
|
+
_raw['aggregations'] ? load_aggs_results(_raw['aggregations'], _formatter) : {}
|
38
|
+
)
|
38
39
|
end
|
39
40
|
|
40
41
|
private
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Elastic::Nodes
|
2
|
+
class Sort < Base
|
3
|
+
ORDER = [:asc, :desc]
|
4
|
+
MODES = [:min, :max, :sum, :avg, :median]
|
5
|
+
|
6
|
+
attr_accessor :child
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@sorts = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def sorts
|
13
|
+
@sorts.dup
|
14
|
+
end
|
15
|
+
|
16
|
+
def add_sort(_field, order: :asc, mode: nil, missing: nil)
|
17
|
+
raise ArgumentError, "invalid sort order #{order}" unless ORDER.include?(order.to_sym)
|
18
|
+
raise ArgumentError, "invalid sort mode #{mode}" if mode && !MODES.include?(mode.to_sym)
|
19
|
+
|
20
|
+
options = { 'order' => order.to_s }
|
21
|
+
options['mode'] = mode.to_s if mode.present?
|
22
|
+
options['missing'] = missing if missing.present?
|
23
|
+
|
24
|
+
@sorts << { _field => options.freeze }.freeze
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_score_sort(order: :desc)
|
29
|
+
raise ArgumentError, "invalid sort order #{order}" unless ORDER.include?(order.to_sym)
|
30
|
+
|
31
|
+
add_sort('_score', order: order)
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset_sorts
|
35
|
+
@sorts = []
|
36
|
+
self
|
37
|
+
end
|
38
|
+
|
39
|
+
def clone
|
40
|
+
prepare_clone(super, child.try(:clone))
|
41
|
+
end
|
42
|
+
|
43
|
+
def simplify
|
44
|
+
if @sorts.empty?
|
45
|
+
child.try(:simplify)
|
46
|
+
else
|
47
|
+
prepare_clone(super, child.try(:simplify))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def render(_options = {})
|
52
|
+
hash = child.render(_options)
|
53
|
+
hash['sort'] = render_sorts
|
54
|
+
hash
|
55
|
+
end
|
56
|
+
|
57
|
+
def handle_result(_raw, _formatter)
|
58
|
+
@child.handle_result(_raw, _formatter)
|
59
|
+
end
|
60
|
+
|
61
|
+
def traverse(&_block)
|
62
|
+
super
|
63
|
+
@child.traverse(&_block)
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
attr_writer :sorts
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def prepare_clone(_clone, _child)
|
73
|
+
_clone.child = _child
|
74
|
+
_clone.sorts = @sorts.dup
|
75
|
+
_clone
|
76
|
+
end
|
77
|
+
|
78
|
+
def render_sorts
|
79
|
+
@sorts.dup
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/elastic/nodes/term.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Elastic::Nodes
|
2
2
|
class Term < Base
|
3
3
|
include Concerns::Boostable
|
4
|
+
include Concerns::FieldQuery
|
4
5
|
|
5
6
|
BOOLEAN_MODE = [:any, :all]
|
6
7
|
|
@@ -30,19 +31,19 @@ module Elastic::Nodes
|
|
30
31
|
prepare_clone(super)
|
31
32
|
end
|
32
33
|
|
33
|
-
def render
|
34
|
-
raise ArgumentError,
|
34
|
+
def render(_options = {})
|
35
|
+
raise ArgumentError, "terms not provided for #{@field}" if !@terms
|
35
36
|
|
36
37
|
if @terms.length == 1
|
37
|
-
{ 'term' => {
|
38
|
-
elsif @mode == :all
|
38
|
+
{ 'term' => { render_field(_options) => render_boost('value' => @terms.first) } }
|
39
|
+
elsif @mode == :all && !@terms.empty?
|
39
40
|
{
|
40
41
|
'bool' => render_boost(
|
41
|
-
'must' => @terms.map { |t| { 'term' => {
|
42
|
+
'must' => @terms.map { |t| { 'term' => { render_field(_options) => t } } }
|
42
43
|
)
|
43
44
|
}
|
44
45
|
else
|
45
|
-
{ 'terms' => render_boost(
|
46
|
+
{ 'terms' => render_boost(render_field(_options) => @terms) }
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
data/lib/elastic/query.rb
CHANGED
@@ -14,10 +14,6 @@ module Elastic
|
|
14
14
|
@config = _query_config || build_base_config
|
15
15
|
end
|
16
16
|
|
17
|
-
def coord_similarity(_enable)
|
18
|
-
with_clone { |config| config.root.query.disable_coord = !_enable }
|
19
|
-
end
|
20
|
-
|
21
17
|
def limit(_size)
|
22
18
|
with_clone { |config| config.limit = _size }
|
23
19
|
end
|
@@ -27,6 +23,12 @@ module Elastic
|
|
27
23
|
with_clone { |config| config.offset = _offset }
|
28
24
|
end
|
29
25
|
|
26
|
+
def sort(*_params)
|
27
|
+
with_clone do |config|
|
28
|
+
config.sort = Commands::BuildSortFromParams.for(index: index, params: _params)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
30
32
|
def segment(*_params)
|
31
33
|
with_clone do |config|
|
32
34
|
config.groups << Commands::BuildAggFromParams.for(index: index, params: _params)
|
@@ -37,8 +39,8 @@ module Elastic
|
|
37
39
|
execute assembler.assemble_ids
|
38
40
|
end
|
39
41
|
|
40
|
-
def
|
41
|
-
execute assembler.
|
42
|
+
def pick(_field)
|
43
|
+
execute assembler.assemble_pick(_field)
|
42
44
|
end
|
43
45
|
|
44
46
|
def aggregate(_name = nil, _node = nil, &_block)
|
@@ -54,6 +56,10 @@ module Elastic
|
|
54
56
|
@result ||= execute(assembler.assemble)
|
55
57
|
end
|
56
58
|
|
59
|
+
def as_query_node
|
60
|
+
@config.query.clone
|
61
|
+
end
|
62
|
+
|
57
63
|
def as_es_query
|
58
64
|
assembler.assemble.render
|
59
65
|
end
|
@@ -67,7 +73,7 @@ module Elastic
|
|
67
73
|
end
|
68
74
|
|
69
75
|
def with_bool_query(&_block)
|
70
|
-
with_clone { |config| _block.call(config.
|
76
|
+
with_clone { |config| _block.call(config.query) }
|
71
77
|
end
|
72
78
|
|
73
79
|
def with_aggregable_for_metric(&_block)
|
@@ -79,15 +85,21 @@ module Elastic
|
|
79
85
|
Core::QueryConfig.initial_config
|
80
86
|
end
|
81
87
|
|
82
|
-
def assembler
|
83
|
-
@assembler ||= Core::QueryAssembler.new(@index, @config)
|
84
|
-
end
|
85
|
-
|
86
88
|
def execute(_query)
|
87
|
-
|
89
|
+
raw = @index.adaptor.query(
|
88
90
|
type: @index.definition.types,
|
89
91
|
query: _query.render
|
90
92
|
)
|
93
|
+
|
94
|
+
_query.handle_result(raw, formatter)
|
95
|
+
end
|
96
|
+
|
97
|
+
def assembler
|
98
|
+
Core::QueryAssembler.new(@index, @config)
|
99
|
+
end
|
100
|
+
|
101
|
+
def formatter
|
102
|
+
Core::SourceFormatter.new(@index.definition)
|
91
103
|
end
|
92
104
|
|
93
105
|
class AggregableAdaptor
|