elastic-rails 0.1.0 → 0.5.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/Guardfile +46 -0
- data/elastic.gemspec +13 -4
- data/lib/elastic/commands/build_agg_from_params.rb +63 -0
- data/lib/elastic/commands/build_query_from_params.rb +132 -0
- data/lib/elastic/commands/import_index_documents.rb +63 -0
- data/lib/elastic/configuration.rb +61 -0
- data/lib/elastic/core/adaptor.rb +102 -0
- data/lib/elastic/core/base_middleware.rb +43 -0
- data/lib/elastic/core/default_middleware.rb +64 -0
- data/lib/elastic/core/definition.rb +118 -0
- data/lib/elastic/core/mapping_manager.rb +120 -0
- data/lib/elastic/core/middleware.rb +26 -0
- data/lib/elastic/core/query_assembler.rb +84 -0
- data/lib/elastic/core/query_config.rb +25 -0
- data/lib/elastic/core/serializer.rb +45 -0
- data/lib/elastic/core/source_formatter.rb +40 -0
- data/lib/elastic/dsl/bool_query_builder.rb +52 -0
- data/lib/elastic/dsl/bool_query_context.rb +42 -0
- data/lib/elastic/dsl/metric_builder.rb +34 -0
- data/lib/elastic/fields/nested.rb +42 -0
- data/lib/elastic/fields/value.rb +60 -0
- data/lib/elastic/nested_type.rb +5 -0
- data/lib/elastic/nodes/agg/average.rb +7 -0
- data/lib/elastic/nodes/agg/base_metric.rb +42 -0
- data/lib/elastic/nodes/agg/date_histogram.rb +48 -0
- data/lib/elastic/nodes/agg/maximum.rb +7 -0
- data/lib/elastic/nodes/agg/minimum.rb +7 -0
- data/lib/elastic/nodes/agg/stats.rb +7 -0
- data/lib/elastic/nodes/agg/sum.rb +7 -0
- data/lib/elastic/nodes/agg/terms.rb +38 -0
- data/lib/elastic/nodes/agg/top_hits.rb +17 -0
- data/lib/elastic/nodes/and.rb +45 -0
- data/lib/elastic/nodes/base.rb +34 -0
- data/lib/elastic/nodes/base_agg.rb +32 -0
- data/lib/elastic/nodes/boolean.rb +87 -0
- data/lib/elastic/nodes/concerns/aggregable.rb +52 -0
- data/lib/elastic/nodes/concerns/boostable.rb +25 -0
- data/lib/elastic/nodes/concerns/bucketed.rb +17 -0
- data/lib/elastic/nodes/concerns/hit_provider.rb +39 -0
- data/lib/elastic/nodes/function_score.rb +116 -0
- data/lib/elastic/nodes/match.rb +45 -0
- data/lib/elastic/nodes/nested.rb +42 -0
- data/lib/elastic/nodes/or.rb +9 -0
- data/lib/elastic/nodes/range.rb +36 -0
- data/lib/elastic/nodes/search.rb +48 -0
- data/lib/elastic/nodes/term.rb +58 -0
- data/lib/elastic/query.rb +84 -22
- data/lib/elastic/railtie.rb +41 -0
- data/lib/elastic/railties/ar_helpers.rb +51 -0
- data/lib/elastic/railties/ar_middleware.rb +45 -0
- data/lib/elastic/{indexable_record.rb → railties/indexable_record.rb} +21 -18
- data/lib/elastic/railties/query_extensions.rb +9 -0
- data/lib/elastic/railties/rspec.rb +6 -0
- data/lib/elastic/railties/tasks/es.rake +19 -0
- data/lib/elastic/railties/type_extensions.rb +14 -0
- data/lib/elastic/railties/utils.rb +62 -0
- data/lib/elastic/results/aggregations.rb +29 -0
- data/lib/elastic/results/base.rb +13 -0
- data/lib/elastic/results/bucket.rb +15 -0
- data/lib/elastic/results/bucket_collection.rb +17 -0
- data/lib/elastic/results/grouped_result.rb +37 -0
- data/lib/elastic/results/hit.rb +25 -0
- data/lib/elastic/results/hit_collection.rb +38 -0
- data/lib/elastic/results/metric.rb +13 -0
- data/lib/elastic/results/result_group.rb +19 -0
- data/lib/elastic/results/root.rb +15 -0
- data/lib/elastic/shims/base.rb +23 -0
- data/lib/elastic/shims/grouping.rb +23 -0
- data/lib/elastic/shims/populating.rb +69 -0
- data/lib/elastic/shims/reducing.rb +20 -0
- data/lib/elastic/support/command.rb +34 -0
- data/lib/elastic/support/transform.rb +37 -0
- data/lib/elastic/support/traversable.rb +22 -0
- data/lib/elastic/type.rb +56 -84
- data/lib/elastic/types/base_type.rb +38 -0
- data/lib/elastic/types/faceted_type.rb +16 -0
- data/lib/elastic/types/nestable_type.rb +14 -0
- data/lib/elastic/version.rb +1 -1
- data/lib/elastic.rb +72 -30
- data/lib/generators/elastic/index_generator.rb +10 -0
- data/lib/generators/elastic/templates/index.rb +17 -0
- metadata +222 -16
- data/lib/elastic/capabilities/aggregation_builder.rb +0 -64
- data/lib/elastic/capabilities/bool_query_builder.rb +0 -74
- data/lib/elastic/capabilities/context_handler.rb +0 -31
- data/lib/elastic/histogram.rb +0 -49
- data/lib/elastic/index.rb +0 -113
- data/lib/elastic/indexable.rb +0 -25
- data/lib/elastic/value_transform.rb +0 -15
@@ -0,0 +1,42 @@
|
|
1
|
+
module Elastic::Nodes::Agg
|
2
|
+
class BaseMetric < Elastic::Nodes::BaseAgg
|
3
|
+
def self.build(_name, _field, missing: nil)
|
4
|
+
super(_name).tap do |node|
|
5
|
+
node.field = _field
|
6
|
+
node.missing = missing
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_accessor :field, :missing
|
11
|
+
|
12
|
+
def clone
|
13
|
+
prepare_clone super
|
14
|
+
end
|
15
|
+
|
16
|
+
def simplify
|
17
|
+
prepare_clone super
|
18
|
+
end
|
19
|
+
|
20
|
+
def render
|
21
|
+
options = { 'field' => @field.to_s }
|
22
|
+
options['missing'] = @missing if @missing
|
23
|
+
|
24
|
+
{ metric => options }
|
25
|
+
end
|
26
|
+
|
27
|
+
def handle_result(_raw)
|
28
|
+
Elastic::Results::Metric.new _raw['value']
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def metric
|
34
|
+
end
|
35
|
+
|
36
|
+
def prepare_clone(_clone)
|
37
|
+
_clone.field = @field
|
38
|
+
_clone.missing = @missing
|
39
|
+
_clone
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Elastic::Nodes::Agg
|
2
|
+
class DateHistogram < Elastic::Nodes::BaseAgg
|
3
|
+
include Elastic::Nodes::Concerns::Aggregable
|
4
|
+
include Elastic::Nodes::Concerns::Bucketed
|
5
|
+
|
6
|
+
def self.build(_name, _field, interval: nil)
|
7
|
+
super(_name).tap do |node|
|
8
|
+
node.field = _field
|
9
|
+
node.interval = interval
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :field
|
14
|
+
attr_reader :interval
|
15
|
+
|
16
|
+
def interval=(_value)
|
17
|
+
raise ArgumentError, 'invalid interval' if _value && !valid_interval?(_value)
|
18
|
+
@interval = _value
|
19
|
+
end
|
20
|
+
|
21
|
+
def clone
|
22
|
+
prepare_clone(super)
|
23
|
+
end
|
24
|
+
|
25
|
+
def simplify
|
26
|
+
prepare_clone(super)
|
27
|
+
end
|
28
|
+
|
29
|
+
def render
|
30
|
+
options = { 'field' => @field.to_s }
|
31
|
+
options['interval'] = @interval if @interval
|
32
|
+
|
33
|
+
render_aggs 'date_histogram' => options
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def prepare_clone(_clone)
|
39
|
+
_clone.field = @field
|
40
|
+
_clone.interval = @interval
|
41
|
+
_clone
|
42
|
+
end
|
43
|
+
|
44
|
+
def valid_interval?(_value)
|
45
|
+
/^\d+(\.\d+)?(y|M|w|d|h|m|s)$/ === _value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Elastic::Nodes::Agg
|
2
|
+
class Terms < Elastic::Nodes::BaseAgg
|
3
|
+
include Elastic::Nodes::Concerns::Aggregable
|
4
|
+
include Elastic::Nodes::Concerns::Bucketed
|
5
|
+
|
6
|
+
def self.build(_name, _field, size: nil)
|
7
|
+
super(_name).tap do |node|
|
8
|
+
node.field = _field
|
9
|
+
node.size = size
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :field, :size
|
14
|
+
|
15
|
+
def clone
|
16
|
+
prepare_clone(super)
|
17
|
+
end
|
18
|
+
|
19
|
+
def simplify
|
20
|
+
prepare_clone(super)
|
21
|
+
end
|
22
|
+
|
23
|
+
def render
|
24
|
+
options = { 'field' => @field.to_s }
|
25
|
+
options['size'] = @size if @size
|
26
|
+
|
27
|
+
render_aggs 'terms' => options
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def prepare_clone(_clone)
|
33
|
+
_clone.field = @field
|
34
|
+
_clone.size = @size
|
35
|
+
_clone
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Elastic::Nodes
|
2
|
+
class TopHits < BaseAgg
|
3
|
+
include Concerns::HitProvider
|
4
|
+
|
5
|
+
def render
|
6
|
+
options = {}
|
7
|
+
render_hit_options options
|
8
|
+
|
9
|
+
{ 'top_hits' => options }
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle_result(_raw)
|
13
|
+
hits = _raw['hits'] ? _raw['hits']['hits'].map { |h| Elastic::Results::Hit.new h } : []
|
14
|
+
Elastic::Results::HitCollection.new(hits)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Elastic::Nodes
|
2
|
+
class And < Base
|
3
|
+
def self.build(_children)
|
4
|
+
new.tap { |node| node.children = _children }
|
5
|
+
end
|
6
|
+
|
7
|
+
def add_child(_child)
|
8
|
+
@children << _child
|
9
|
+
end
|
10
|
+
|
11
|
+
def children=(_value)
|
12
|
+
@children = _value.dup.to_a
|
13
|
+
end
|
14
|
+
|
15
|
+
def traverse(&_block)
|
16
|
+
super
|
17
|
+
@children.each { |c| c.traverse(&_block) }
|
18
|
+
end
|
19
|
+
|
20
|
+
def clone
|
21
|
+
prepare_clone super, @children.map(&:clone)
|
22
|
+
end
|
23
|
+
|
24
|
+
def simplify
|
25
|
+
new_children = @children.map(&:simplify)
|
26
|
+
return new_children.first if new_children.count == 1
|
27
|
+
prepare_clone(super, new_children)
|
28
|
+
end
|
29
|
+
|
30
|
+
def render
|
31
|
+
{ operation => @children.map(&:render) }
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def prepare_clone(_clone, _children)
|
37
|
+
_clone.children = _children
|
38
|
+
_clone
|
39
|
+
end
|
40
|
+
|
41
|
+
def operation
|
42
|
+
'and'
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Elastic::Nodes
|
2
|
+
class Base
|
3
|
+
include Elastic::Support::Traversable
|
4
|
+
|
5
|
+
def ==(_node)
|
6
|
+
render == _node.render
|
7
|
+
end
|
8
|
+
|
9
|
+
def traverse(&_block)
|
10
|
+
_block.call(self)
|
11
|
+
end
|
12
|
+
|
13
|
+
def render
|
14
|
+
raise NotImplementedError, 'render must be implemented by each node'
|
15
|
+
end
|
16
|
+
|
17
|
+
def clone
|
18
|
+
self.class.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def simplify
|
22
|
+
self.class.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_result(_raw)
|
26
|
+
nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
require "elastic/nodes/concerns/hit_provider"
|
32
|
+
require "elastic/nodes/concerns/aggregable"
|
33
|
+
require "elastic/nodes/concerns/bucketed"
|
34
|
+
require "elastic/nodes/concerns/boostable"
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Elastic::Nodes
|
2
|
+
class BaseAgg < Base
|
3
|
+
attr_reader :name
|
4
|
+
|
5
|
+
def self.build(_name)
|
6
|
+
new.tap { |n| n.name = _name }
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@name = 'default'
|
11
|
+
end
|
12
|
+
|
13
|
+
def name=(_value)
|
14
|
+
@name = _value.to_s
|
15
|
+
end
|
16
|
+
|
17
|
+
def clone
|
18
|
+
copy_name super
|
19
|
+
end
|
20
|
+
|
21
|
+
def simplify
|
22
|
+
copy_name super
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def copy_name(_clone)
|
28
|
+
_clone.name = @name
|
29
|
+
_clone
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Elastic::Nodes
|
2
|
+
class Boolean < Base
|
3
|
+
include Concerns::Boostable
|
4
|
+
|
5
|
+
def self.build_and(_nodes)
|
6
|
+
new.tap { |n| n.musts = _nodes }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.build_or(_nodes)
|
10
|
+
new.tap { |n| n.shoulds = _nodes }
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_accessor :minimum_should_match, :disable_coord
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
super
|
17
|
+
@musts = []
|
18
|
+
@shoulds = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def must(_node)
|
22
|
+
@musts << _node
|
23
|
+
end
|
24
|
+
|
25
|
+
def should(_node)
|
26
|
+
@shoulds << _node
|
27
|
+
end
|
28
|
+
|
29
|
+
def musts=(_nodes)
|
30
|
+
@musts = _nodes.dup.to_a
|
31
|
+
end
|
32
|
+
|
33
|
+
def musts
|
34
|
+
@musts.each
|
35
|
+
end
|
36
|
+
|
37
|
+
def shoulds=(_nodes)
|
38
|
+
@shoulds = _nodes.dup.to_a
|
39
|
+
end
|
40
|
+
|
41
|
+
def shoulds
|
42
|
+
@shoulds.each
|
43
|
+
end
|
44
|
+
|
45
|
+
def traverse(&_block)
|
46
|
+
super
|
47
|
+
@shoulds.each { |c| c.traverse(&_block) }
|
48
|
+
@musts.each { |c| c.traverse(&_block) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def render
|
52
|
+
options = {}.tap do |boolean|
|
53
|
+
boolean['must'] = @musts.map(&:render) if !@musts.empty?
|
54
|
+
boolean['should'] = @shoulds.map(&:render) if !@shoulds.empty?
|
55
|
+
boolean['minimum_should_match'] = minimum_should_match unless minimum_should_match.nil?
|
56
|
+
boolean['disable_coord'] = true if disable_coord
|
57
|
+
render_boost(boolean)
|
58
|
+
end
|
59
|
+
|
60
|
+
{ "bool" => options }
|
61
|
+
end
|
62
|
+
|
63
|
+
def clone
|
64
|
+
prepare_clone super, @musts.map(&:clone), @shoulds.map(&:clone)
|
65
|
+
end
|
66
|
+
|
67
|
+
def simplify
|
68
|
+
new_must = @musts.map(&:simplify)
|
69
|
+
new_should = @shoulds.map(&:simplify)
|
70
|
+
|
71
|
+
return new_must.first if new_must.length == 1 && new_should.empty?
|
72
|
+
return new_should.first if new_should.length == 1 && new_must.empty? # at least 1 should match
|
73
|
+
|
74
|
+
prepare_clone(super, new_must, new_should)
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def prepare_clone(_clone, _musts, _shoulds)
|
80
|
+
_clone.musts = _musts
|
81
|
+
_clone.shoulds = _shoulds
|
82
|
+
_clone.minimum_should_match = @minimum_should_match
|
83
|
+
_clone.disable_coord = @disable_coord
|
84
|
+
_clone
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Elastic::Nodes::Concerns
|
2
|
+
module Aggregable
|
3
|
+
def has_aggs?
|
4
|
+
aggs.count > 0
|
5
|
+
end
|
6
|
+
|
7
|
+
def aggs=(_aggs)
|
8
|
+
@aggs = _aggs.dup.to_a
|
9
|
+
end
|
10
|
+
|
11
|
+
def aggregate(_node)
|
12
|
+
raise ArgumentError, 'node must provide a name' unless _node.name
|
13
|
+
aggs << _node
|
14
|
+
end
|
15
|
+
|
16
|
+
def traverse(&_block)
|
17
|
+
super
|
18
|
+
aggs.each { |a| a.traverse(&_block) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def clone
|
22
|
+
node = super
|
23
|
+
node.aggs = aggs.map(&:clone)
|
24
|
+
node
|
25
|
+
end
|
26
|
+
|
27
|
+
def simplify
|
28
|
+
node = super
|
29
|
+
node.aggs = aggs.map(&:simplify)
|
30
|
+
node
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def aggs
|
36
|
+
@aggs ||= []
|
37
|
+
end
|
38
|
+
|
39
|
+
def render_aggs(_into)
|
40
|
+
_into['aggs'] = Hash[aggs.map { |a| [a.name, a.render] }] if has_aggs?
|
41
|
+
_into
|
42
|
+
end
|
43
|
+
|
44
|
+
def load_aggs_results(_raw)
|
45
|
+
{}.tap do |result|
|
46
|
+
aggs.each do |node|
|
47
|
+
result[node.name] = node.handle_result(_raw[node.name])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Elastic::Nodes::Concerns
|
2
|
+
module Boostable
|
3
|
+
attr_accessor :boost
|
4
|
+
|
5
|
+
def clone
|
6
|
+
copy_boost super
|
7
|
+
end
|
8
|
+
|
9
|
+
def simplify
|
10
|
+
copy_boost super
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def copy_boost(_clone)
|
16
|
+
_clone.boost = @boost
|
17
|
+
_clone
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_boost(_hash)
|
21
|
+
_hash['boost'] = @boost.to_f unless @boost.nil?
|
22
|
+
_hash
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Elastic::Nodes::Concerns
|
2
|
+
module Bucketed
|
3
|
+
def handle_result(_raw)
|
4
|
+
buckets = _raw['buckets'].map do |raw_bucket|
|
5
|
+
aggs = load_aggs_results(raw_bucket)
|
6
|
+
|
7
|
+
# TODO: allow bucket aggregation to return single nested aggregation if node is
|
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)
|
12
|
+
end
|
13
|
+
|
14
|
+
Elastic::Results::BucketCollection.new buckets
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Elastic::Nodes::Concerns
|
2
|
+
module HitProvider
|
3
|
+
attr_accessor :size
|
4
|
+
attr_reader :source
|
5
|
+
|
6
|
+
def source=(_values)
|
7
|
+
case _values
|
8
|
+
when nil, false
|
9
|
+
@source = _values
|
10
|
+
when Array, Enumerable
|
11
|
+
@source = _values.dup.to_a
|
12
|
+
else
|
13
|
+
raise ArgumentError, 'invalid query source value'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def clone
|
18
|
+
copy_hit_options super
|
19
|
+
end
|
20
|
+
|
21
|
+
def simplify
|
22
|
+
copy_hit_options super
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def copy_hit_options(_clone)
|
28
|
+
_clone.size = @size
|
29
|
+
_clone.source = @source
|
30
|
+
_clone
|
31
|
+
end
|
32
|
+
|
33
|
+
def render_hit_options(_hash)
|
34
|
+
_hash['size'] = @size unless @size.nil?
|
35
|
+
_hash["_source"] = @source unless @source.nil?
|
36
|
+
_hash
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module Elastic::Nodes
|
2
|
+
class FunctionScore < Base
|
3
|
+
include Concerns::Boostable
|
4
|
+
|
5
|
+
SCORE_MODES = [:multiply, :sum, :avg, :first, :max, :min]
|
6
|
+
BOOST_MODES = [:multiply, :replace, :sum, :avg, :max, :min]
|
7
|
+
|
8
|
+
def self.build(_query)
|
9
|
+
new.tap { |node| node.query = _query }
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :query
|
13
|
+
attr_reader :score_mode, :boost_mode
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@functions = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def functions=(_values)
|
20
|
+
@functions = _values.dup.to_a
|
21
|
+
end
|
22
|
+
|
23
|
+
def score_mode=(_value)
|
24
|
+
raise ArgumentError, "invalid score mode #{_value}" if _value && !SCORE_MODES.include?(_value)
|
25
|
+
@score_mode = _value
|
26
|
+
end
|
27
|
+
|
28
|
+
def boost_mode=(_value)
|
29
|
+
raise ArgumentError, "invalid boost mode #{_value}" if _value && !BOOST_MODES.include?(_value)
|
30
|
+
@boost_mode = _value
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_weight_function(_weight, filter: nil)
|
34
|
+
add_function(nil, nil, filter, _weight)
|
35
|
+
end
|
36
|
+
|
37
|
+
def add_field_function(_field, factor: 1, modifier: :none, missing: 1, weight: nil, filter: nil)
|
38
|
+
params = {
|
39
|
+
'field' => _field,
|
40
|
+
'factor' => factor,
|
41
|
+
'modifier' => modifier,
|
42
|
+
'missing' => missing
|
43
|
+
}
|
44
|
+
|
45
|
+
add_function('field_value_factor', params, filter, weight)
|
46
|
+
end
|
47
|
+
|
48
|
+
def add_decay_function(_field, _options = {})
|
49
|
+
raise NotImplementedError, 'decay function not implemented'
|
50
|
+
end
|
51
|
+
|
52
|
+
def traverse(&_block)
|
53
|
+
super
|
54
|
+
@query.traverse(&_block)
|
55
|
+
end
|
56
|
+
|
57
|
+
def render
|
58
|
+
function_score = { 'query' => @query.render }
|
59
|
+
function_score['boost_mode'] = @boost_mode.to_s if @boost_mode && @boost_mode != :multiply
|
60
|
+
|
61
|
+
if @functions.length > 1
|
62
|
+
function_score['score_mode'] = @score_mode.to_s if @score_mode && @score_mode != :multiply
|
63
|
+
function_score['functions'] = @functions
|
64
|
+
elsif @functions.length == 1
|
65
|
+
function_score.merge! @functions.first
|
66
|
+
end
|
67
|
+
|
68
|
+
{ 'function_score' => render_boost(function_score) }
|
69
|
+
end
|
70
|
+
|
71
|
+
alias :super_clone :clone
|
72
|
+
private :super_clone
|
73
|
+
|
74
|
+
def clone
|
75
|
+
prepare_clone super, @query.clone
|
76
|
+
end
|
77
|
+
|
78
|
+
def clone_with_query(_query)
|
79
|
+
prepare_clone super_clone, _query
|
80
|
+
end
|
81
|
+
|
82
|
+
def simplify
|
83
|
+
new_query = query.simplify
|
84
|
+
|
85
|
+
if @functions.empty?
|
86
|
+
return new_query if boost.nil?
|
87
|
+
|
88
|
+
if new_query.class.include?(Concerns::Boostable) && new_query.boost.nil?
|
89
|
+
new_query.boost = boost
|
90
|
+
return new_query
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
prepare_clone(super, new_query)
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
def add_function(_function, _params, _filter, _weight)
|
100
|
+
@functions << {}.tap do |hash|
|
101
|
+
hash[_function] = _params if _function
|
102
|
+
hash['weight'] = _weight unless _weight.nil?
|
103
|
+
hash['filter'] = _filter.render unless _filter.nil?
|
104
|
+
end
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def prepare_clone(_clone, _query)
|
109
|
+
_clone.query = _query
|
110
|
+
_clone.functions = @functions
|
111
|
+
_clone.boost_mode = @boost_mode
|
112
|
+
_clone.score_mode = @score_mode
|
113
|
+
_clone
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Elastic::Nodes
|
2
|
+
class Match < Base
|
3
|
+
include Concerns::Boostable
|
4
|
+
|
5
|
+
MATCH_MODES = [:boolean, :phrase, :phrase_prefix]
|
6
|
+
|
7
|
+
attr_accessor :field, :query
|
8
|
+
attr_reader :mode
|
9
|
+
|
10
|
+
def query=(_query)
|
11
|
+
raise ArgumentError, 'query must be a string' unless _query.is_a? String
|
12
|
+
@query = _query
|
13
|
+
end
|
14
|
+
|
15
|
+
def mode=(_value)
|
16
|
+
_value = _value.try(:to_sym)
|
17
|
+
raise ArgumentError, 'invalid match mode' if !_value.nil? && !MATCH_MODES.include?(_value)
|
18
|
+
@mode = _value
|
19
|
+
end
|
20
|
+
|
21
|
+
def clone
|
22
|
+
prepare_clone(super)
|
23
|
+
end
|
24
|
+
|
25
|
+
def simplify
|
26
|
+
prepare_clone(super)
|
27
|
+
end
|
28
|
+
|
29
|
+
def render
|
30
|
+
query_options = { 'query' => @query }
|
31
|
+
query_options['type'] = @mode.to_s unless @mode.nil? || @mode == :boolean
|
32
|
+
|
33
|
+
{ "match" => { @field.to_s => render_boost(query_options) } }
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def prepare_clone(_clone)
|
39
|
+
_clone.field = @field
|
40
|
+
_clone.query = @query
|
41
|
+
_clone.mode = @mode
|
42
|
+
_clone
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|