elastic-rails 0.1.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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