elasticband 0.1.2 → 0.1.3

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,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d2a30bee92116c46bbf3eb5a39cb92be290a026d
4
- data.tar.gz: 92dac622a6d60f5ab215112fa0e6ea0654c5dd73
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MWNjYjdlNWNlYzIwZWRhMzg5M2YwOGNkNGI3MzE5ZjAwZjkxYjM1NA==
5
+ data.tar.gz: !binary |-
6
+ M2ViMmE2ZDNiY2VkOTg4ZGE2ODgyNTA0MjY1OGNkOGRjMDI3ZDUwMA==
5
7
  SHA512:
6
- metadata.gz: 194f5bba732ba55c01c472a87b699c2f441e23715e562fdaea06747f52ac887ecca6b200ac3337a51aebc8a99ba7b0220340c41e35d7e8b7f16db9eba6901869
7
- data.tar.gz: 8b5618650450007a892a32c484bf1d4478211a460d66128ab52416c776ef4a14b7450e4cfad48fadae5849e0a36242a26fffc91e236707d23f84b751e98b6c5e
8
+ metadata.gz: !binary |-
9
+ YzI3NDFiOGQ3ZTUxNDI1ZTY4ZjdmZDNkOTJiOGI1NmM0NTlmODFjYTk2NGM2
10
+ NTRkNTA3N2VjYTNlNTE1NjIzYTNiM2Q4ZDhhMGMyMWIwMGI0ODUwM2NiMzY5
11
+ MWI3NDBmY2YwMWNkZWE5NmExNzFhOTBlNjlkOTdiM2I4OTQ3MDA=
12
+ data.tar.gz: !binary |-
13
+ NDkyYjZkNzVlMTEwOTcwNzgxZTAxYTM1MDQzMzY2ZjZjYTcxMTI4YzgxZTJi
14
+ ODM2NzhiMjg3OTZhN2RhNjE0OGU0MGRmN2VlYzM5YTcwNGU1ZTA3OTBkYTVk
15
+ ZmI2ZWY1MTVlN2IyZWRiNzk3ZjY4ZTRjN2FiZmMwNzQzZmRiN2E=
data/.travis.yml CHANGED
@@ -1,13 +1,23 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  rvm:
4
- - 2.2
5
- - ruby-head
4
+ - 2.2
5
+ - ruby-head
6
6
  git:
7
7
  depth: 1
8
8
  script:
9
- - bundle exec rspec
10
- - bundle exec rubocop
11
- addons:
9
+ - bundle exec rspec
10
+ - bundle exec rubocop
11
+ add_ons:
12
12
  code_climate:
13
- repo_token: 217146fc082e87b5e4b2352141a8832d0da78d66a9d22cb0b5189344648e821e
13
+ repo_token:
14
+ secure: J7KZY6qcRup/D/m1v4dau0UZ4S1UQ5aW+PYago1jMvTZ/KqyPP36rAiRZhzCROjVaodbkwxhGfp+V9eLPGZG+CF3yFAZWCa+YaOR4ihbx7PI+o1KB5Rvo/LfoXTZ2ietGLSHf43ae617pp5uu6IF7scl5NQqaXraE/zQYce4wOWAYTQvxi+lnYHYbPWtAtsBoCNTyFdscHT5LPSGIINaGsPVwVp5WSoOe770vNLqnoPD/FAlB71scCfO5oOrPu1jeQf7kHXNuJGFeVCauSrC23oAcYs15RO8F5LZIH5ikR7wBpaK3TEv98GR27xZaMiP07IGiaXXG0AOWM1wxk4kUuy7jE7Rgd/Q5DU9HlO7pf1RWKRKeJTBocez2SmtGVQjQ1cIqhzmZI/QXipkYuSKUB4HZsKhQMCIZqW5dR9OomviJbrOHSQRNcGhtKWSzgxHAlhC8Fel57jgU/CTZyFoiaFL/qFvddo98CJriPsKGbQFtsXdOE2r5GyS0VOZW8XKpyhvH9E1RKaxnsopfL2Gh/BOZAh7ZI1XWTS7QJQMYHPLsxkf1gQa29T1GV+lo53fuv55HDrJHZ3dphAAngjCQRs6hNdB/m2KgqognwNXrnVRrpSlMq4yvyRHSmfiatXl10bw7iFzQ+h227PP+CzXtRwJlHj5FpUc/voNE0oOaeA=
15
+ deploy:
16
+ provider: rubygems
17
+ api_key:
18
+ secure: GuPR9kqmSoQKhgh/SBpa2+zysNHv3n92hsuA7MyZ0ezgdN41qdZqYJb/w5hZLBuGyDJO8f+Ib1deKw8+3gQO6rsiFwlVW6nrPEcxCRjg/QQSxNk2FuPxh2FF7/n9Ce3ePeVhnmkCAw7++B7OLUo5Un8cR35WHPzChrprQ1RLpbSB6Qg8nwcW92aju6WqUkHrdYEyP/Q94oqzA09gamth8flCPYw8XKeklR8aQ6KkdD4w96Bu3AwBOYbUkIlNNXXj1CCvWwcJf5DQ+DR6JMk0KkaniLxrsSmiTBkVlUIJfEIJMUUuPiAUZ0tvwFtc5Puys987YwpNmqq4eqB3Hxp85FLDEEgxECtlBz5Ab8/rgUuJxlHI6kLPgOw6sseTmTYLG4NJkGj/icjP7LaQYSIry+LVnncM48YIC9nzuBNsF6XfFXfLAAq+u51FFJVF0SihqWYKFSk96d+UHuOtitVQ6Smte4ir+7ifclMgtxgYqBzX50Pv39uysvSpmFYpVkGXiGnVjHAffWhNOVJDJdF2K0BllJP2PyNF4fDrheFNS6lQj394aewCGkvLzyHIht903KC8+IvD4u4KQktA7q/ctn6dODfjXUn6eIaS5lXYeLNI7OHUR8fsMDJyiNEleBHKVs9KAVqjKJFsaH/ZY90VuAQ/3U/J3a3PsCHUZ2iDuTU=
19
+ gem: elasticband
20
+ on:
21
+ tags: true
22
+ repo: LoveMondays/elasticband
23
+ branch: master
data/lib/elasticband.rb CHANGED
@@ -1,6 +1,7 @@
1
- require 'active_support'
2
- require 'active_support/core_ext/object'
3
1
  require 'active_support/core_ext/array'
2
+ require 'active_support/core_ext/hash'
3
+ require 'active_support/core_ext/object'
4
+ require 'active_support/json'
4
5
 
5
6
  require 'elasticband/aggregation'
6
7
  require 'elasticband/filter'
@@ -1,3 +1,5 @@
1
+ require 'elasticband/aggregation/field_based'
2
+ require 'elasticband/aggregation/max'
1
3
  require 'elasticband/aggregation/nested'
2
4
  require 'elasticband/aggregation/terms'
3
5
  require 'elasticband/aggregation/top_hits'
@@ -7,7 +9,7 @@ module Elasticband
7
9
  attr_accessor :name
8
10
 
9
11
  def initialize(name)
10
- self.name = name.to_sym
12
+ self.name = name.to_s.gsub(/\W/, '_').to_sym
11
13
  end
12
14
 
13
15
  def to_h(aggregation_hash = {})
@@ -15,40 +17,81 @@ module Elasticband
15
17
  end
16
18
 
17
19
  class << self
18
- # Parses some options to a Elasticsearch syntax
20
+ PARSE_AGGREGATIONS = %i(group_by group_max top_hits)
21
+
22
+ # Parses some options to a Elasticsearch syntax, aggregations can be nested in another.
19
23
  #
20
24
  # #### Options
21
25
  #
22
26
  # * `group_by:` Count results by the value of an attribute using `terms` filter.
23
27
  # It can receive an array with some attributes:
24
- # * `top_hits:` A number of results that should be return inside the group ranked by score.
25
28
  # * `size:` Size of the results calculated in each shard (https://www.elastic.co/guide/en/elasticsearch/reference/1.x/search-aggregations-bucket-terms-aggregation.html#_size)
29
+ # * `script:` Generates terms defined by the script
30
+ # * `group_max:` Group results by maximum value of a field
31
+ # It can receive an array with some attributes:
32
+ # * `script:` Generates max defined by the script
33
+ # * `top_hits:` A number of results that should be return inside the group ranked by score.
26
34
  #
27
35
  # #### Examples
28
36
  # ```
29
37
  # Aggregation.parse(group_by: :status)
30
38
  # => { status: { terms: { field: :status } } }
31
39
  #
40
+ # Aggregation.parse(group_max: :contents_count)
41
+ # => { status: { max: { field: :contents_count } } }
42
+ #
32
43
  # Aggregation.parse(group_by: [:status, size: 5, top_hits: 3])
33
44
  # => { status: { terms: { field: :status, size: 5 }, aggs: { top_status: { top_hits: 3 } } } }
34
45
  def parse(options)
35
- parse_group_by(options[:group_by]).to_h
46
+ merge(*parse_aggregations(options))
47
+ end
48
+
49
+ def merge(*aggregations)
50
+ aggregations.each_with_object({}) { |a, h| h.merge!(a.to_h) }
36
51
  end
37
52
 
38
53
  private
39
54
 
40
- def parse_group_by(options_group_by)
41
- return {} if options_group_by.blank?
55
+ def parse_aggregations(options, root_aggregation = nil)
56
+ parse_options = options.slice(*PARSE_AGGREGATIONS)
57
+ return root_aggregation if parse_options.blank?
42
58
 
43
- field, options = options_group_by
44
- options ||= {}
59
+ aggregations = parse_options.map do |aggregation_name, aggregation_options|
60
+ parse_singular_aggregation(root_aggregation, aggregation_name, aggregation_options)
61
+ end
62
+
63
+ aggregations = Aggregation::Nested.new(root_aggregation, aggregations) if root_aggregation
64
+ aggregations
65
+ end
45
66
 
46
- aggregation = Aggregation::Terms.new(field, field, options.except(:top_hits))
47
- if options[:top_hits]
48
- aggregation = Aggregation::TopHits.new(:"top_#{field}", aggregation, options[:top_hits])
67
+ def parse_singular_aggregation(root_aggregation, aggregation_name, aggregation_options)
68
+ case aggregation_name
69
+ when :group_by then parse_field_aggregation(Aggregation::Terms, :by, aggregation_options)
70
+ when :group_max then parse_field_aggregation(Aggregation::Max, :max, aggregation_options)
71
+ when :top_hits then parse_top_hits(root_aggregation, aggregation_options)
49
72
  end
73
+ end
74
+
75
+ def parse_field_aggregation(aggregation_class, prefix, options_aggregation)
76
+ return {} if options_aggregation.blank?
77
+
78
+ field, options = options_aggregation
79
+ options ||= {}
80
+
81
+ name = :"#{prefix}_#{field}"
82
+ aggregation = aggregation_class.new(name, field, options.except(*PARSE_AGGREGATIONS))
83
+ parse_aggregations(options, aggregation)
84
+ end
85
+
86
+ def parse_top_hits(root_aggregation, options_top_hits)
87
+ return {} if options_top_hits.blank?
88
+
89
+ size, options = options_top_hits
90
+ options ||= {}
50
91
 
51
- aggregation
92
+ name = :"top_#{root_aggregation.name}"
93
+ aggregation = Aggregation::TopHits.new(name, size, options.except(*PARSE_AGGREGATIONS))
94
+ parse_aggregations(options, aggregation)
52
95
  end
53
96
  end
54
97
  end
@@ -0,0 +1,27 @@
1
+ module Elasticband
2
+ class Aggregation
3
+ class FieldBased < Aggregation
4
+ attr_accessor :field, :options
5
+
6
+ def initialize(name, field, options = {})
7
+ super(name)
8
+ self.field = field && field.to_sym
9
+ self.options = options
10
+ end
11
+
12
+ def to_h
13
+ super(aggregation_hash)
14
+ end
15
+
16
+ def type
17
+ fail NotImplementedError
18
+ end
19
+
20
+ private
21
+
22
+ def aggregation_hash
23
+ { type => { field: field }.merge!(options).compact }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,9 @@
1
+ module Elasticband
2
+ class Aggregation
3
+ class Max < FieldBased
4
+ def type
5
+ :max
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,18 +1,24 @@
1
1
  module Elasticband
2
2
  class Aggregation
3
3
  class Nested < Aggregation
4
- attr_accessor :root_aggregation, :nested_aggregation
4
+ attr_accessor :root_aggregation, :nested_aggregations
5
5
 
6
- def initialize(root_aggregation, nested_aggregation)
6
+ def initialize(root_aggregation, nested_aggregations)
7
7
  self.root_aggregation = root_aggregation
8
- self.nested_aggregation = nested_aggregation
8
+ self.nested_aggregations = Array.wrap(nested_aggregations)
9
9
  end
10
10
 
11
11
  def to_h
12
12
  root_aggregation.to_h.tap do |h|
13
- h[root_aggregation.name].merge!(aggs: nested_aggregation.to_h)
13
+ h[root_aggregation.name].merge!(aggs: nested_hash)
14
14
  end
15
15
  end
16
+
17
+ private
18
+
19
+ def nested_hash
20
+ self.class.merge(*nested_aggregations)
21
+ end
16
22
  end
17
23
  end
18
24
  end
@@ -1,22 +1,8 @@
1
1
  module Elasticband
2
2
  class Aggregation
3
- class Terms < Aggregation
4
- attr_accessor :field, :options
5
-
6
- def initialize(name, field, options = {})
7
- super(name)
8
- self.field = field.to_sym
9
- self.options = options
10
- end
11
-
12
- def to_h
13
- super(aggregation_hash)
14
- end
15
-
16
- private
17
-
18
- def aggregation_hash
19
- { terms: { field: field }.merge!(options) }
3
+ class Terms < FieldBased
4
+ def type
5
+ :terms
20
6
  end
21
7
  end
22
8
  end
@@ -1,19 +1,16 @@
1
1
  module Elasticband
2
2
  class Aggregation
3
3
  class TopHits < Aggregation
4
- attr_accessor :root_aggregation, :size, :from, :options
4
+ attr_accessor :size, :options
5
5
 
6
- def initialize(name, root_aggregation, size, options = {})
6
+ def initialize(name, size, options = {})
7
7
  super(name)
8
- self.root_aggregation = root_aggregation
9
8
  self.size = size
10
9
  self.options = options
11
10
  end
12
11
 
13
12
  def to_h
14
- root_aggregation.to_h.tap do |h|
15
- h[root_aggregation.name].merge!(aggs: super(top_hits_hash))
16
- end
13
+ super(top_hits_hash)
17
14
  end
18
15
 
19
16
  private
@@ -139,7 +139,8 @@ module Elasticband
139
139
  filter = join_filters(parse_filters(boost_options[:boost_where]))
140
140
  ScoreFunction::Filtered.new(filter, ScoreFunction::BoostFactor.new(1_000))
141
141
  else
142
- ScoreFunction::ScriptScore.new(boost_options[:boost_function])
142
+ boost_function, boost_function_params = boost_options[:boost_function]
143
+ ScoreFunction::ScriptScore.new(boost_function, boost_function_params || {})
143
144
  end
144
145
  end
145
146
  end
@@ -1,3 +1,3 @@
1
1
  module Elasticband
2
- VERSION = '0.1.2'
2
+ VERSION = '0.1.3'
3
3
  end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Elasticband::Aggregation::FieldBased do
4
+ describe '#type' do
5
+ subject { described_class.new(:aggregation_name, :field_name).type }
6
+
7
+ it { expect { subject }.to raise_error(NotImplementedError) }
8
+ end
9
+
10
+ describe '#to_h' do
11
+ subject { aggregation.to_h }
12
+
13
+ before { allow(aggregation).to receive(:type) { :aggregation_type } }
14
+
15
+ context 'without options' do
16
+ let(:aggregation) { described_class.new(:aggregation_name, :field_name) }
17
+
18
+ it { is_expected.to eq(aggregation_name: { aggregation_type: { field: :field_name } }) }
19
+ end
20
+
21
+ context 'with options' do
22
+ context 'with field' do
23
+ let(:aggregation) { described_class.new(:aggregation_name, :field_name, size: 1) }
24
+
25
+ it { is_expected.to eq(aggregation_name: { aggregation_type: { field: :field_name, size: 1 } }) }
26
+ end
27
+
28
+ context 'without field' do
29
+ let(:aggregation) { described_class.new(:aggregation_name, nil, script: "doc['price'].value") }
30
+
31
+ it { is_expected.to eq(aggregation_name: { aggregation_type: { script: "doc['price'].value" } }) }
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Elasticband::Aggregation::Max do
4
+ describe '#type' do
5
+ subject { described_class.new(:aggregation_name, :field_name).type }
6
+
7
+ it { is_expected.to eq(:max) }
8
+ end
9
+ end
@@ -2,27 +2,52 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Elasticband::Aggregation::Nested do
4
4
  describe '#to_h' do
5
- subject { described_class.new(root_aggregation, nested_aggregation).to_h }
6
-
7
5
  let(:root_aggregation) { Elasticband::Aggregation.new(:root_aggregation) }
8
- let(:nested_aggregation) { Elasticband::Aggregation.new(:nested_aggregation) }
6
+ let(:nested_aggregation_1) { Elasticband::Aggregation.new(:nested_aggregation_1) }
7
+ let(:nested_aggregation_2) { Elasticband::Aggregation.new(:nested_aggregation_2) }
8
+ let(:nested_aggregations) { [nested_aggregation_1, nested_aggregation_2] }
9
9
 
10
10
  before do
11
- allow(root_aggregation).to receive(:to_h) { { root_aggregation: { key_1: :value_1 } } }
12
- allow(nested_aggregation).to receive(:to_h) { { nested_aggregation: { key_2: :value_2 } } }
11
+ allow(nested_aggregation_1).to receive(:to_h) { { nested_aggregation_1: { key_1: :value_1 } } }
12
+ allow(nested_aggregation_2).to receive(:to_h) { { nested_aggregation_2: { key_2: :value_2 } } }
13
+ allow(root_aggregation).to receive(:to_h) { { root_aggregation: { key: :value } } }
13
14
  end
14
15
 
15
- it 'returns a nested aggreagation hash' do
16
- is_expected.to eq(
17
- root_aggregation: {
18
- key_1: :value_1,
19
- aggs: {
20
- nested_aggregation: {
21
- key_2: :value_2
16
+ context 'with one aggregation' do
17
+ subject { described_class.new(root_aggregation, nested_aggregation_1).to_h }
18
+
19
+ it 'returns a nested aggreagation hash' do
20
+ is_expected.to eq(
21
+ root_aggregation: {
22
+ key: :value,
23
+ aggs: {
24
+ nested_aggregation_1: {
25
+ key_1: :value_1
26
+ }
27
+ }
28
+ }
29
+ )
30
+ end
31
+ end
32
+
33
+ context 'with two aggregations' do
34
+ subject { described_class.new(root_aggregation, nested_aggregations).to_h }
35
+
36
+ it 'returns a nested aggreagation hash' do
37
+ is_expected.to eq(
38
+ root_aggregation: {
39
+ key: :value,
40
+ aggs: {
41
+ nested_aggregation_1: {
42
+ key_1: :value_1
43
+ },
44
+ nested_aggregation_2: {
45
+ key_2: :value_2
46
+ }
22
47
  }
23
48
  }
24
- }
25
- )
49
+ )
50
+ end
26
51
  end
27
52
  end
28
53
  end
@@ -1,17 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  RSpec.describe Elasticband::Aggregation::Terms do
4
- describe '#to_h' do
5
- context 'without options' do
6
- subject { described_class.new(:aggregation_name, :field_name).to_h }
4
+ describe '#type' do
5
+ subject { described_class.new(:aggregation_name, :field_name).type }
7
6
 
8
- it { is_expected.to eq(aggregation_name: { terms: { field: :field_name } }) }
9
- end
10
-
11
- context 'with options' do
12
- subject { described_class.new(:aggregation_name, :field_name, size: 1).to_h }
13
-
14
- it { is_expected.to eq(aggregation_name: { terms: { field: :field_name, size: 1 } }) }
15
- end
7
+ it { is_expected.to eq(:terms) }
16
8
  end
17
9
  end
@@ -2,25 +2,16 @@ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Elasticband::Aggregation::TopHits do
4
4
  describe '#to_h' do
5
- subject { described_class.new(:top_hits_aggregation, root_aggregation, 3).to_h }
5
+ context 'without options' do
6
+ subject { described_class.new(:top_hits_aggregation, 3).to_h }
6
7
 
7
- let(:root_aggregation) { Elasticband::Aggregation.new(:root_aggregation) }
8
-
9
- before do
10
- allow(root_aggregation).to receive(:to_h) { { root_aggregation: { terms: { field: :field_name } } } }
8
+ it { is_expected.to eq(top_hits_aggregation: { top_hits: { size: 3 } }) }
11
9
  end
12
10
 
13
- it 'returns a nested aggreagation hash' do
14
- is_expected.to eq(
15
- root_aggregation: {
16
- terms: { field: :field_name },
17
- aggs: {
18
- top_hits_aggregation: {
19
- top_hits: { size: 3 }
20
- }
21
- }
22
- }
23
- )
11
+ context 'with options' do
12
+ subject { described_class.new(:top_hits_aggregation, 3, cache: true).to_h }
13
+
14
+ it { is_expected.to eq(top_hits_aggregation: { top_hits: { size: 3, cache: true } }) }
24
15
  end
25
16
  end
26
17
  end
@@ -13,6 +13,12 @@ RSpec.describe Elasticband::Aggregation do
13
13
 
14
14
  it { is_expected.to eq(aggregation_name: { key: :value }) }
15
15
  end
16
+
17
+ context 'with special chars' do
18
+ subject { described_class.new('aggregation.name').to_h }
19
+
20
+ it { is_expected.to eq(aggregation_name: {}) }
21
+ end
16
22
  end
17
23
 
18
24
  describe '.parse' do
@@ -22,17 +28,17 @@ RSpec.describe Elasticband::Aggregation do
22
28
  context 'with the field_name' do
23
29
  let(:options) { { group_by: :status } }
24
30
 
25
- it { is_expected.to eq(status: { terms: { field: :status } }) }
31
+ it { is_expected.to eq(by_status: { terms: { field: :status } }) }
26
32
  end
27
33
 
28
- context 'with an array with field_name and :top_hits option' do
34
+ context 'with an array with field_name and other aggregation' do
29
35
  let(:options) { { group_by: [:status, top_hits: 3] } }
30
36
 
31
37
  it 'returns the `terms` aggregation with a `top_hits` nested' do
32
38
  is_expected.to eq(
33
- status: {
39
+ by_status: {
34
40
  terms: { field: :status },
35
- aggs: { top_status: { top_hits: { size: 3 } } }
41
+ aggs: { top_by_status: { top_hits: { size: 3 } } }
36
42
  }
37
43
  )
38
44
  end
@@ -41,8 +47,52 @@ RSpec.describe Elasticband::Aggregation do
41
47
  context 'with an array with field_name and other options' do
42
48
  let(:options) { { group_by: [:status, size: 3] } }
43
49
 
44
- it { is_expected.to eq(status: { terms: { field: :status, size: 3 } }) }
50
+ it { is_expected.to eq(by_status: { terms: { field: :status, size: 3 } }) }
51
+ end
52
+ end
53
+
54
+ context 'with `:group_max` option' do
55
+ context 'with the field_name' do
56
+ let(:options) { { group_max: :price } }
57
+
58
+ it { is_expected.to eq(max_price: { max: { field: :price } }) }
59
+ end
60
+
61
+ context 'with an array with field_name and options' do
62
+ let(:options) { { group_max: [:price, script: '_value * 1.2'] } }
63
+
64
+ it { is_expected.to eq(max_price: { max: { field: :price, script: '_value * 1.2' } }) }
45
65
  end
46
66
  end
67
+
68
+ context 'with more than one aggregation' do
69
+ let(:options) { { group_by: :status, group_max: :price } }
70
+
71
+ it 'returns a hash with all aggregations' do
72
+ is_expected.to eq(
73
+ by_status: { terms: { field: :status } },
74
+ max_price: { max: { field: :price } }
75
+ )
76
+ end
77
+ end
78
+ end
79
+
80
+ describe '.merge' do
81
+ subject { described_class.merge(aggregation_1, aggregation_2) }
82
+
83
+ let(:aggregation_1) { Elasticband::Aggregation.new(:aggregation_1) }
84
+ let(:aggregation_2) { Elasticband::Aggregation.new(:aggregation_2) }
85
+
86
+ before do
87
+ allow(aggregation_1).to receive(:to_h) { { aggregation_1: { key_1: :value_1 } } }
88
+ allow(aggregation_2).to receive(:to_h) { { aggregation_2: { key_2: :value_2 } } }
89
+ end
90
+
91
+ it 'returns a hash with all aggregations' do
92
+ is_expected.to eq(
93
+ aggregation_1: { key_1: :value_1 },
94
+ aggregation_2: { key_2: :value_2 }
95
+ )
96
+ end
47
97
  end
48
98
  end
data/spec/query_spec.rb CHANGED
@@ -219,17 +219,37 @@ RSpec.describe Elasticband::Query do
219
219
  end
220
220
 
221
221
  context 'with `:boost_function` option' do
222
- let(:options) { { boost_function: "_score * doc['users_count'].value" } }
222
+ context 'without params' do
223
+ let(:options) { { boost_function: "_score * doc['users_count'].value" } }
223
224
 
224
- it 'returns a function score query with a `script_score` function' do
225
- is_expected.to eq(
226
- function_score: {
227
- query: { match: { _all: 'foo' } },
228
- script_score: {
229
- script: "_score * doc['users_count'].value"
225
+ it 'returns a function score query with a `script_score` function' do
226
+ is_expected.to eq(
227
+ function_score: {
228
+ query: { match: { _all: 'foo' } },
229
+ script_score: {
230
+ script: "_score * doc['users_count'].value"
231
+ }
230
232
  }
231
- }
232
- )
233
+ )
234
+ end
235
+ end
236
+
237
+ context 'with params' do
238
+ let(:options) { { boost_function: ['_score * test_param', params: { test_param: 1 }] } }
239
+
240
+ it 'returns a function score query with a `script_score` function and params' do
241
+ is_expected.to eq(
242
+ function_score: {
243
+ query: { match: { _all: 'foo' } },
244
+ script_score: {
245
+ script: '_score * test_param',
246
+ params: {
247
+ test_param: 1
248
+ }
249
+ }
250
+ }
251
+ )
252
+ end
233
253
  end
234
254
  end
235
255
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticband
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glauber Campinho
@@ -15,84 +15,84 @@ dependencies:
15
15
  name: activesupport
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ">="
18
+ - - ! '>='
19
19
  - !ruby/object:Gem::Version
20
20
  version: '0'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ">="
25
+ - - ! '>='
26
26
  - !ruby/object:Gem::Version
27
27
  version: '0'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: dotenv
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ">="
32
+ - - ! '>='
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
35
  type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ">="
39
+ - - ! '>='
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: rake
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ">="
46
+ - - ! '>='
47
47
  - !ruby/object:Gem::Version
48
48
  version: '0'
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ">="
53
+ - - ! '>='
54
54
  - !ruby/object:Gem::Version
55
55
  version: '0'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: rspec
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - "~>"
60
+ - - ~>
61
61
  - !ruby/object:Gem::Version
62
62
  version: 3.3.0
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - "~>"
67
+ - - ~>
68
68
  - !ruby/object:Gem::Version
69
69
  version: 3.3.0
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: rubocop
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ">="
74
+ - - ! '>='
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ">="
81
+ - - ! '>='
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: codeclimate-test-reporter
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - ">="
88
+ - - ! '>='
89
89
  - !ruby/object:Gem::Version
90
90
  version: '0'
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - ">="
95
+ - - ! '>='
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0'
98
98
  description:
@@ -103,10 +103,10 @@ executables: []
103
103
  extensions: []
104
104
  extra_rdoc_files: []
105
105
  files:
106
- - ".gitignore"
107
- - ".rspec"
108
- - ".rubocop.yml"
109
- - ".travis.yml"
106
+ - .gitignore
107
+ - .rspec
108
+ - .rubocop.yml
109
+ - .travis.yml
110
110
  - CODE_OF_CONDUCT.md
111
111
  - Gemfile
112
112
  - LICENSE
@@ -115,6 +115,8 @@ files:
115
115
  - elasticband.gemspec
116
116
  - lib/elasticband.rb
117
117
  - lib/elasticband/aggregation.rb
118
+ - lib/elasticband/aggregation/field_based.rb
119
+ - lib/elasticband/aggregation/max.rb
118
120
  - lib/elasticband/aggregation/nested.rb
119
121
  - lib/elasticband/aggregation/terms.rb
120
122
  - lib/elasticband/aggregation/top_hits.rb
@@ -136,6 +138,8 @@ files:
136
138
  - lib/elasticband/query/score_function/script_score.rb
137
139
  - lib/elasticband/search.rb
138
140
  - lib/elasticband/version.rb
141
+ - spec/aggregation/field_based_spec.rb
142
+ - spec/aggregation/max_spec.rb
139
143
  - spec/aggregation/nested_spec.rb
140
144
  - spec/aggregation/terms_spec.rb
141
145
  - spec/aggregation/top_hits_spec.rb
@@ -168,17 +172,17 @@ require_paths:
168
172
  - lib
169
173
  required_ruby_version: !ruby/object:Gem::Requirement
170
174
  requirements:
171
- - - ">="
175
+ - - ! '>='
172
176
  - !ruby/object:Gem::Version
173
177
  version: '0'
174
178
  required_rubygems_version: !ruby/object:Gem::Requirement
175
179
  requirements:
176
- - - ">="
180
+ - - ! '>='
177
181
  - !ruby/object:Gem::Version
178
182
  version: '0'
179
183
  requirements: []
180
184
  rubyforge_project:
181
- rubygems_version: 2.4.7
185
+ rubygems_version: 2.4.5
182
186
  signing_key:
183
187
  specification_version: 4
184
188
  summary: Query builder for elasticsearch-rails