elastic-rails 0.8.5 → 0.8.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4479b2e301ba75acb8449d5afb042efaf249511c
4
- data.tar.gz: 6f456debe94dcaa755a3a5e8e45e1de0ed53264a
3
+ metadata.gz: c0035b5db3d49f0a734e2f8a2d77162ac50867cc
4
+ data.tar.gz: 0223a10c669b8f637b14c50afe88b73ef4714a17
5
5
  SHA512:
6
- metadata.gz: c4015950ebd08be302993e16ca68ddc8641e9038fb9198a661d670569642ceae4324a978c9deb8c5cd410443d5fa0b3c6d69dacac3b9c1670fb66f5a4ed68e98
7
- data.tar.gz: b929a60ed947548975264fd69c68935e7cb3dca1a0dea9372aa8986d1f372979a58f27ba28318841308c7d4444a6ea399793f490d6c0829bb3954ed90329be80
6
+ metadata.gz: f95a7f7abbaae72da092ec05cbfc2fc5cdec442438d48acbcfab152a716a84c0deb1f3e2e1ae60196a756608d73753203861f8337ccabd9a1353110f720fb19d
7
+ data.tar.gz: 4f3fe1093d986f8fcda505c37623a5da5398a93bb0a407408c32863ffe33e14d161244617fa0b6247e4dfc1b946695d23931136ab9b9512d437e8db82aa28dfd
data/.travis.yml CHANGED
@@ -1,5 +1,8 @@
1
- sudo: false
2
1
  language: ruby
3
2
  rvm:
4
- - 2.3.1
5
- before_install: gem install bundler -v 1.12.4
3
+ - 2.4.0
4
+ - 2.3.3
5
+ - 2.2.6
6
+ services:
7
+ - elasticsearch
8
+ before_install: gem install bundler -v 1.12.5
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Elastic Rails
2
2
 
3
+ [![Build Status](https://travis-ci.org/platanus/elastic-rails.svg?branch=master)](https://travis-ci.org/platanus/elastic-rails)
4
+
3
5
  Elasticsearch + Ruby on Rails made easy.
4
6
 
5
7
  ## Features
@@ -119,6 +121,14 @@ BikeIndex
119
121
  .average(:price)
120
122
  .each { |keys, price| puts "#{keys[:year]}/#{keys[:category]} => #{price}" }
121
123
 
124
+ # Get average and maximum bike price for bikes newer than 2014
125
+ BikeIndex
126
+ .must(year: { gte: 2014 })
127
+ .compose do |c|
128
+ c.average(:price)
129
+ c.maximum(:price)
130
+ end
131
+
122
132
  # Search bikes ids that have shimano parts:
123
133
  BikeIndex.must(parts: { brand: 'shimano' }).ids
124
134
  ```
data/lib/elastic.rb CHANGED
@@ -45,6 +45,7 @@ require "elastic/nodes/agg/average"
45
45
  require "elastic/nodes/agg/minimum"
46
46
  require "elastic/nodes/agg/maximum"
47
47
  require "elastic/nodes/agg/sum"
48
+ require "elastic/nodes/agg/top"
48
49
  require "elastic/nodes/agg/terms"
49
50
  require "elastic/nodes/agg/date_histogram"
50
51
  require "elastic/nodes/agg/top_hits"
@@ -52,7 +53,8 @@ require "elastic/nodes/agg/top_hits"
52
53
  require "elastic/shims/base"
53
54
  require "elastic/shims/populating"
54
55
  require "elastic/shims/grouping"
55
- require "elastic/shims/reducing"
56
+ require "elastic/shims/single_aggregation"
57
+ require "elastic/shims/multiple_aggregation"
56
58
  require "elastic/shims/total_picking"
57
59
  require "elastic/shims/id_picking"
58
60
  require "elastic/shims/field_picking"
@@ -79,6 +81,7 @@ require "elastic/core/query_assembler"
79
81
  require "elastic/dsl/bool_query_builder"
80
82
  require "elastic/dsl/bool_query_context"
81
83
  require "elastic/dsl/metric_builder"
84
+ require "elastic/dsl/result_composer"
82
85
 
83
86
  require "elastic/types/base_type"
84
87
  require "elastic/types/faceted_type"
@@ -30,11 +30,16 @@ module Elastic::Core
30
30
  end
31
31
 
32
32
  def assemble_metric(_node)
33
- query = assemble_metrics([_node])
34
- reduced_query query
33
+ query = assemble_aggregated([_node])
34
+ single_aggregation_query query
35
35
  end
36
36
 
37
- def assemble_metrics(_aggs)
37
+ def assemble_metrics(_nodes)
38
+ query = assemble_aggregated(_nodes)
39
+ multiple_aggregation_query query
40
+ end
41
+
42
+ def assemble_aggregated(_aggs)
38
43
  query = build_base_query
39
44
  query.size = 0
40
45
 
@@ -64,7 +69,7 @@ module Elastic::Core
64
69
  last.aggregate sort_node Elastic::Nodes::TopHits.build('default')
65
70
 
66
71
  query = grouped_query query
67
- query = reduced_query query
72
+ query = single_aggregation_query query
68
73
  end
69
74
 
70
75
  query
@@ -93,8 +98,12 @@ module Elastic::Core
93
98
  Elastic::Shims::Grouping.new(_query)
94
99
  end
95
100
 
96
- def reduced_query(_query)
97
- Elastic::Shims::Reducing.new(_query)
101
+ def single_aggregation_query(_query)
102
+ Elastic::Shims::SingleAggregation.new(_query)
103
+ end
104
+
105
+ def multiple_aggregation_query(_query)
106
+ Elastic::Shims::MultipleAggregation.new(_query)
98
107
  end
99
108
 
100
109
  def populated_query(_query)
@@ -20,15 +20,32 @@ module Elastic::Dsl
20
20
  aggregate_metric(Elastic::Nodes::Agg::Stats, _field, _options, '%s_stats')
21
21
  end
22
22
 
23
- private
23
+ def opening(_field, _options = {})
24
+ by = _options.delete :by
25
+ raise ArgumentError, 'must provide a sorting column' if by.nil?
26
+
27
+ aggregate_metric(Elastic::Nodes::Agg::Top, _field, _options, 'open_%s') do |node|
28
+ node.add_sort(by, order: :asc)
29
+ end
30
+ end
31
+
32
+ def closing(_field, _options = {})
33
+ by = _options.delete :by
34
+ raise ArgumentError, 'must provide a sorting column' if by.nil?
24
35
 
25
- def aggregate_metric(_klass, _field, _options, _default_name)
26
- with_aggregable_for_metric do |agg|
27
- # TODO: detect nested name and wrap node
28
- name = _options[:as] || sprintf(_default_name, _field)
29
- node = _klass.build(name, _field, missing: _options[:missing])
30
- agg.aggregate node
36
+ aggregate_metric(Elastic::Nodes::Agg::Top, _field, _options, 'close_%s') do |node|
37
+ node.add_sort(by, order: :desc)
31
38
  end
32
39
  end
40
+
41
+ private
42
+
43
+ def aggregate_metric(_klass, _field, _options, _default_name, &_block)
44
+ # TODO: detect nested name and wrap node
45
+ name = _options.delete(:as) || sprintf(_default_name, _field)
46
+ node = _klass.build(name, _field, _options)
47
+ _block.call node unless _block.nil?
48
+ aggregate node
49
+ end
33
50
  end
34
51
  end
@@ -0,0 +1,15 @@
1
+ module Elastic::Dsl
2
+ class ResultComposer
3
+ include MetricBuilder
4
+
5
+ def initialize(_aggs)
6
+ @aggs = _aggs
7
+ end
8
+
9
+ def aggregate(_node)
10
+ raise ArgumentError, 'node must provide a name' unless _node.name
11
+ @aggs << _node
12
+ nil
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,42 @@
1
+ module Elastic::Nodes::Agg
2
+ class Top < Elastic::Nodes::BaseAgg
3
+ include Elastic::Nodes::Concerns::Sortable
4
+
5
+ def self.build(_name, _field, _options = {})
6
+ super(_name).tap do |node|
7
+ node.field = _field
8
+ end
9
+ end
10
+
11
+ attr_accessor :field
12
+
13
+ def clone
14
+ prepare_clone super
15
+ end
16
+
17
+ def simplify
18
+ prepare_clone super
19
+ end
20
+
21
+ def render(_options = {})
22
+ top_hit_config = { '_source' => { 'include' => [@field.to_s] }, 'size' => 1 }
23
+ top_hit_config['sort'] = render_sorts if registered_sorts.count > 0
24
+
25
+ { 'top_hits' => top_hit_config }
26
+ end
27
+
28
+ def handle_result(_raw, _formatter)
29
+ raw_value = _raw['hits'] ? _raw['hits']['hits'].first['_source'][@field.to_s] : nil
30
+
31
+ # TODO: apply formatter to value
32
+ Elastic::Results::Metric.new raw_value
33
+ end
34
+
35
+ private
36
+
37
+ def prepare_clone(_clone)
38
+ _clone.field = @field
39
+ _clone
40
+ end
41
+ end
42
+ end
@@ -33,4 +33,4 @@ require "elastic/nodes/concerns/aggregable"
33
33
  require "elastic/nodes/concerns/bucketed"
34
34
  require "elastic/nodes/concerns/boostable"
35
35
  require "elastic/nodes/concerns/field_query"
36
-
36
+ require "elastic/nodes/concerns/sortable"
@@ -0,0 +1,54 @@
1
+ module Elastic::Nodes::Concerns
2
+ module Sortable
3
+ ORDER = [:asc, :desc]
4
+ MODES = [:min, :max, :sum, :avg, :median]
5
+
6
+ def clone
7
+ copy_sorts super
8
+ end
9
+
10
+ def simplify
11
+ copy_sorts super
12
+ end
13
+
14
+ def sorts
15
+ registered_sorts.dup
16
+ end
17
+
18
+ def add_sort(_field, order: :asc, mode: nil, missing: nil)
19
+ raise ArgumentError, "invalid sort order #{order}" unless ORDER.include?(order.to_sym)
20
+ raise ArgumentError, "invalid sort mode #{mode}" if mode && !MODES.include?(mode.to_sym)
21
+
22
+ options = { 'order' => order.to_s }
23
+ options['mode'] = mode.to_s if mode.present?
24
+ options['missing'] = missing if missing.present?
25
+
26
+ registered_sorts << { _field.to_s => options.freeze }.freeze
27
+ self
28
+ end
29
+
30
+ def reset_sorts
31
+ @registered_sorts = nil
32
+ self
33
+ end
34
+
35
+ protected
36
+
37
+ attr_writer :registered_sorts
38
+
39
+ private
40
+
41
+ def copy_sorts(_clone)
42
+ _clone.registered_sorts = sorts
43
+ _clone
44
+ end
45
+
46
+ def render_sorts
47
+ sorts
48
+ end
49
+
50
+ def registered_sorts
51
+ @registered_sorts ||= []
52
+ end
53
+ end
54
+ end
@@ -1,47 +1,19 @@
1
1
  module Elastic::Nodes
2
2
  class Sort < Base
3
- ORDER = [:asc, :desc]
4
- MODES = [:min, :max, :sum, :avg, :median]
3
+ include Concerns::Sortable
5
4
 
6
5
  attr_accessor :child
7
6
 
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
7
  def add_score_sort(order: :desc)
29
- raise ArgumentError, "invalid sort order #{order}" unless ORDER.include?(order.to_sym)
30
-
31
8
  add_sort('_score', order: order)
32
9
  end
33
10
 
34
- def reset_sorts
35
- @sorts = []
36
- self
37
- end
38
-
39
11
  def clone
40
12
  prepare_clone(super, child.try(:clone))
41
13
  end
42
14
 
43
15
  def simplify
44
- if @sorts.empty?
16
+ if registered_sorts.empty?
45
17
  child.try(:simplify)
46
18
  else
47
19
  prepare_clone(super, child.try(:simplify))
@@ -63,20 +35,11 @@ module Elastic::Nodes
63
35
  @child.traverse(&_block)
64
36
  end
65
37
 
66
- protected
67
-
68
- attr_writer :sorts
69
-
70
38
  private
71
39
 
72
40
  def prepare_clone(_clone, _child)
73
41
  _clone.child = _child
74
- _clone.sorts = @sorts.dup
75
42
  _clone
76
43
  end
77
-
78
- def render_sorts
79
- @sorts.dup
80
- end
81
44
  end
82
45
  end
data/lib/elastic/query.rb CHANGED
@@ -43,10 +43,6 @@ module Elastic
43
43
  execute assembler.assemble_pick(_field)
44
44
  end
45
45
 
46
- def aggregate(_name = nil, _node = nil, &_block)
47
- # TODO
48
- end
49
-
50
46
  def total
51
47
  execute assembler.assemble_total
52
48
  end
@@ -64,6 +60,16 @@ module Elastic
64
60
  assembler.assemble.render
65
61
  end
66
62
 
63
+ def compose(&_block)
64
+ agg_nodes = []
65
+ Dsl::ResultComposer.new(agg_nodes).tap(&_block)
66
+ execute assembler.assemble_metrics agg_nodes
67
+ end
68
+
69
+ def aggregate(_node)
70
+ execute assembler.assemble_metric _node
71
+ end
72
+
67
73
  private
68
74
 
69
75
  def with_clone(&_block)
@@ -76,11 +82,6 @@ module Elastic
76
82
  with_clone { |config| _block.call(config.query) }
77
83
  end
78
84
 
79
- def with_aggregable_for_metric(&_block)
80
- adaptor = AggregableAdaptor.new.tap(&_block)
81
- execute assembler.assemble_metric(adaptor.agg)
82
- end
83
-
84
85
  def build_base_config
85
86
  Core::QueryConfig.initial_config
86
87
  end
@@ -101,13 +102,5 @@ module Elastic
101
102
  def formatter
102
103
  Core::SourceFormatter.new(@index.definition)
103
104
  end
104
-
105
- class AggregableAdaptor
106
- attr_accessor :agg
107
-
108
- def aggregate(_node)
109
- self.agg = _node
110
- end
111
- end
112
105
  end
113
106
  end
@@ -0,0 +1,16 @@
1
+ module Elastic::Shims
2
+ class MultipleAggregation < Base
3
+ def handle_result(_raw, _formatter)
4
+ result = super
5
+
6
+ case result
7
+ when Elastic::Results::Root
8
+ result.aggregations
9
+ when Elastic::Results::GroupedResult
10
+ result
11
+ else
12
+ raise "unable to reduce result of type #{result.class}"
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,5 @@
1
1
  module Elastic::Shims
2
- class Reducing < Base
2
+ class SingleAggregation < Base
3
3
  def handle_result(_raw, _formatter)
4
4
  result = super
5
5
 
@@ -1,3 +1,3 @@
1
1
  module Elastic
2
- VERSION = "0.8.5"
2
+ VERSION = "0.8.6"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elastic-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.5
4
+ version: 0.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ignacio Baixas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-03-17 00:00:00.000000000 Z
11
+ date: 2017-05-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: elasticsearch
@@ -248,6 +248,7 @@ files:
248
248
  - lib/elastic/dsl/bool_query_builder.rb
249
249
  - lib/elastic/dsl/bool_query_context.rb
250
250
  - lib/elastic/dsl/metric_builder.rb
251
+ - lib/elastic/dsl/result_composer.rb
251
252
  - lib/elastic/errors.rb
252
253
  - lib/elastic/fields/nested.rb
253
254
  - lib/elastic/fields/value.rb
@@ -261,6 +262,7 @@ files:
261
262
  - lib/elastic/nodes/agg/stats.rb
262
263
  - lib/elastic/nodes/agg/sum.rb
263
264
  - lib/elastic/nodes/agg/terms.rb
265
+ - lib/elastic/nodes/agg/top.rb
264
266
  - lib/elastic/nodes/agg/top_hits.rb
265
267
  - lib/elastic/nodes/and.rb
266
268
  - lib/elastic/nodes/base.rb
@@ -271,6 +273,7 @@ files:
271
273
  - lib/elastic/nodes/concerns/bucketed.rb
272
274
  - lib/elastic/nodes/concerns/field_query.rb
273
275
  - lib/elastic/nodes/concerns/hit_provider.rb
276
+ - lib/elastic/nodes/concerns/sortable.rb
274
277
  - lib/elastic/nodes/function_score.rb
275
278
  - lib/elastic/nodes/match.rb
276
279
  - lib/elastic/nodes/nested.rb
@@ -309,8 +312,9 @@ files:
309
312
  - lib/elastic/shims/field_picking.rb
310
313
  - lib/elastic/shims/grouping.rb
311
314
  - lib/elastic/shims/id_picking.rb
315
+ - lib/elastic/shims/multiple_aggregation.rb
312
316
  - lib/elastic/shims/populating.rb
313
- - lib/elastic/shims/reducing.rb
317
+ - lib/elastic/shims/single_aggregation.rb
314
318
  - lib/elastic/shims/total_picking.rb
315
319
  - lib/elastic/support/command.rb
316
320
  - lib/elastic/support/transform.rb