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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/Guardfile +46 -0
  3. data/elastic.gemspec +13 -4
  4. data/lib/elastic/commands/build_agg_from_params.rb +63 -0
  5. data/lib/elastic/commands/build_query_from_params.rb +132 -0
  6. data/lib/elastic/commands/import_index_documents.rb +63 -0
  7. data/lib/elastic/configuration.rb +61 -0
  8. data/lib/elastic/core/adaptor.rb +102 -0
  9. data/lib/elastic/core/base_middleware.rb +43 -0
  10. data/lib/elastic/core/default_middleware.rb +64 -0
  11. data/lib/elastic/core/definition.rb +118 -0
  12. data/lib/elastic/core/mapping_manager.rb +120 -0
  13. data/lib/elastic/core/middleware.rb +26 -0
  14. data/lib/elastic/core/query_assembler.rb +84 -0
  15. data/lib/elastic/core/query_config.rb +25 -0
  16. data/lib/elastic/core/serializer.rb +45 -0
  17. data/lib/elastic/core/source_formatter.rb +40 -0
  18. data/lib/elastic/dsl/bool_query_builder.rb +52 -0
  19. data/lib/elastic/dsl/bool_query_context.rb +42 -0
  20. data/lib/elastic/dsl/metric_builder.rb +34 -0
  21. data/lib/elastic/fields/nested.rb +42 -0
  22. data/lib/elastic/fields/value.rb +60 -0
  23. data/lib/elastic/nested_type.rb +5 -0
  24. data/lib/elastic/nodes/agg/average.rb +7 -0
  25. data/lib/elastic/nodes/agg/base_metric.rb +42 -0
  26. data/lib/elastic/nodes/agg/date_histogram.rb +48 -0
  27. data/lib/elastic/nodes/agg/maximum.rb +7 -0
  28. data/lib/elastic/nodes/agg/minimum.rb +7 -0
  29. data/lib/elastic/nodes/agg/stats.rb +7 -0
  30. data/lib/elastic/nodes/agg/sum.rb +7 -0
  31. data/lib/elastic/nodes/agg/terms.rb +38 -0
  32. data/lib/elastic/nodes/agg/top_hits.rb +17 -0
  33. data/lib/elastic/nodes/and.rb +45 -0
  34. data/lib/elastic/nodes/base.rb +34 -0
  35. data/lib/elastic/nodes/base_agg.rb +32 -0
  36. data/lib/elastic/nodes/boolean.rb +87 -0
  37. data/lib/elastic/nodes/concerns/aggregable.rb +52 -0
  38. data/lib/elastic/nodes/concerns/boostable.rb +25 -0
  39. data/lib/elastic/nodes/concerns/bucketed.rb +17 -0
  40. data/lib/elastic/nodes/concerns/hit_provider.rb +39 -0
  41. data/lib/elastic/nodes/function_score.rb +116 -0
  42. data/lib/elastic/nodes/match.rb +45 -0
  43. data/lib/elastic/nodes/nested.rb +42 -0
  44. data/lib/elastic/nodes/or.rb +9 -0
  45. data/lib/elastic/nodes/range.rb +36 -0
  46. data/lib/elastic/nodes/search.rb +48 -0
  47. data/lib/elastic/nodes/term.rb +58 -0
  48. data/lib/elastic/query.rb +84 -22
  49. data/lib/elastic/railtie.rb +41 -0
  50. data/lib/elastic/railties/ar_helpers.rb +51 -0
  51. data/lib/elastic/railties/ar_middleware.rb +45 -0
  52. data/lib/elastic/{indexable_record.rb → railties/indexable_record.rb} +21 -18
  53. data/lib/elastic/railties/query_extensions.rb +9 -0
  54. data/lib/elastic/railties/rspec.rb +6 -0
  55. data/lib/elastic/railties/tasks/es.rake +19 -0
  56. data/lib/elastic/railties/type_extensions.rb +14 -0
  57. data/lib/elastic/railties/utils.rb +62 -0
  58. data/lib/elastic/results/aggregations.rb +29 -0
  59. data/lib/elastic/results/base.rb +13 -0
  60. data/lib/elastic/results/bucket.rb +15 -0
  61. data/lib/elastic/results/bucket_collection.rb +17 -0
  62. data/lib/elastic/results/grouped_result.rb +37 -0
  63. data/lib/elastic/results/hit.rb +25 -0
  64. data/lib/elastic/results/hit_collection.rb +38 -0
  65. data/lib/elastic/results/metric.rb +13 -0
  66. data/lib/elastic/results/result_group.rb +19 -0
  67. data/lib/elastic/results/root.rb +15 -0
  68. data/lib/elastic/shims/base.rb +23 -0
  69. data/lib/elastic/shims/grouping.rb +23 -0
  70. data/lib/elastic/shims/populating.rb +69 -0
  71. data/lib/elastic/shims/reducing.rb +20 -0
  72. data/lib/elastic/support/command.rb +34 -0
  73. data/lib/elastic/support/transform.rb +37 -0
  74. data/lib/elastic/support/traversable.rb +22 -0
  75. data/lib/elastic/type.rb +56 -84
  76. data/lib/elastic/types/base_type.rb +38 -0
  77. data/lib/elastic/types/faceted_type.rb +16 -0
  78. data/lib/elastic/types/nestable_type.rb +14 -0
  79. data/lib/elastic/version.rb +1 -1
  80. data/lib/elastic.rb +72 -30
  81. data/lib/generators/elastic/index_generator.rb +10 -0
  82. data/lib/generators/elastic/templates/index.rb +17 -0
  83. metadata +222 -16
  84. data/lib/elastic/capabilities/aggregation_builder.rb +0 -64
  85. data/lib/elastic/capabilities/bool_query_builder.rb +0 -74
  86. data/lib/elastic/capabilities/context_handler.rb +0 -31
  87. data/lib/elastic/histogram.rb +0 -49
  88. data/lib/elastic/index.rb +0 -113
  89. data/lib/elastic/indexable.rb +0 -25
  90. 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,7 @@
1
+ module Elastic::Nodes::Agg
2
+ class Maximum < BaseMetric
3
+ private def metric
4
+ 'max'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Elastic::Nodes::Agg
2
+ class Minimum < BaseMetric
3
+ private def metric
4
+ 'min'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Elastic::Nodes::Agg
2
+ class Stats < BaseMetric
3
+ private def metric
4
+ 'stats'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module Elastic::Nodes::Agg
2
+ class Sum < BaseMetric
3
+ private def metric
4
+ 'sum'
5
+ end
6
+ end
7
+ 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