elasticband 0.2.0 → 0.3.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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- YjQyMGZiM2RiNGJhODg2M2Y2NzViZjNlOGQ4NmNlNWU3YzE2NGEyNA==
4
+ YmE0MWFkZjBhOWEzNjY1ODgzZTkwZGIwMWE2YTc2OWVlZjUwZDc3NQ==
5
5
  data.tar.gz: !binary |-
6
- M2JmMzRkMmZiMDM0NWI5ZWFmNDgwOTVlOTNjN2VmY2IzNTQ5MmVkNg==
6
+ NDNlMGI1Y2VjNjA3ZGYyN2ViZDg2ODhkNzY5YjQ5OTFlMDRkODEyYw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- ZTQwYTA5ZDA0ZmJiMmEwYzkwNGVhZmQyYmRkZmUwY2MxODJjYzU5ZjBkOTFl
10
- NWMxMmJjZDI1NjQ5ZDUyZWMzNDU1NjUzY2VkYjgyNTBmNzk2ZGFlNWI0MGJh
11
- N2YwY2MwN2JmNDRkZDliYWZkZjY1NjRjNjM1NmUyNjU1ZTc5OGU=
9
+ Yjg1MzQ3M2U4ZmY0YWZhNTVhZDVjOThiOGE3NTEwMGY2NWQ0ZDAxNTllODc3
10
+ ZThjZjQ0NDlmMzMwMDg0OWI4NjZhM2MxNjQ4ODQ1OTFiMTgyMmI5NmE0YmQ4
11
+ YTVlZGM1NGQzNDBhNTc4NDMzMGNlNThiMDE3YzJkNTRjY2Y0NDc=
12
12
  data.tar.gz: !binary |-
13
- OGUwMmE0Y2RiMDJiNzdmY2UxMWYzZWYyNTMwNzA4NjkyMzI3YjQzZTQxNmMy
14
- ZGNkYWRmN2Q4NTZlMTMzM2ZhNmJjMGE0OTZlNDY4NTgzNmQ1YmViNTBiODU3
15
- MTU1YTFhMDBkMGRjNzA3MzRhMGE5YTgxZGMxMDBjNGYwMTA4N2I=
13
+ YWYyMmEzMzBhOWQ3Y2ZjZWY4YmVkMmFmODlhNTA0MWI2YWJmNjg4YmNjMGUx
14
+ OWQ2Njk4NTRkMGFlOTQzMmYyNGY1ZmQ4YzkyNGM3YjAzMmQyMzI0MTJkOWY2
15
+ YTViNWEwNTNlMWMzNmIzYWM5MTg3MTU4M2RiMjA5MjM4OGIwMWQ=
@@ -0,0 +1,23 @@
1
+ module Elasticband
2
+ class Filter
3
+ class Near < Filter
4
+ attr_accessor :on, :latitude, :longitude, :distance
5
+
6
+ def initialize(on: :location, latitude: nil, longitude: nil, distance: '100km')
7
+ self.on = on
8
+ self.latitude = latitude
9
+ self.longitude = longitude
10
+ self.distance = distance
11
+ end
12
+
13
+ def to_h
14
+ {
15
+ geo_distance: {
16
+ on => { lat: latitude, lon: longitude },
17
+ distance: distance
18
+ }
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,12 +2,13 @@ require 'elasticband/filter/and'
2
2
  require 'elasticband/filter/not'
3
3
  require 'elasticband/filter/query'
4
4
  require 'elasticband/filter/range'
5
+ require 'elasticband/filter/near'
5
6
  require 'elasticband/filter/term'
6
7
  require 'elasticband/filter/terms'
7
8
 
8
9
  module Elasticband
9
10
  class Filter
10
- PARSE_FILTERS = %i(only except includes range)
11
+ PARSE_FILTERS = %i(only except includes range near)
11
12
 
12
13
  def to_h
13
14
  { match_all: {} }
@@ -22,6 +23,7 @@ module Elasticband
22
23
  # * `except`: Filter the search results where the condition is `false`.
23
24
  # * `includes:` Filter the search results with a `Match` query.
24
25
  # * `range:` Filter the search results where the condition is on the given range.
26
+ # * `near:` Filter the search results where the results are near a geo point.
25
27
  #
26
28
  # #### Examples
27
29
  # ```
@@ -36,35 +38,48 @@ module Elasticband
36
38
  #
37
39
  # Filter.parse(range: { companies_count: { gt: 1, gteq: 1, lt: 1, lteq: 1 } })
38
40
  # => { range: { companies_count: { gt: 1, gte: 1, lt: 1, lte: 1 } } }
41
+ #
42
+ # Filter.parse(near: { latitude: 12, longitude: 34, distance: '5km' })
43
+ # => { geo_distance: { location: { lat: 12, lon: 34 } }, distance: '5km' }
39
44
  # ```
40
45
  def parse(options = {})
41
46
  return {} if options.blank?
42
47
 
43
- filter = parse_filters(options[:only])
44
- filter += parse_filters(options[:except]).map { |f| Filter::Not.new(f) }
45
- filter += parse_includes_filter(options[:includes])
46
- filter += parse_range_filter(options[:range])
48
+ filter = only_and_except_filters(options[:only], options[:except])
49
+ filter += includes_filter(options[:includes])
50
+ filter += range_filter(options[:range])
51
+ filter += near_filter(options[:near])
47
52
  join_filters(filter).to_h
48
53
  end
49
54
 
50
55
  private
51
56
 
57
+ def only_and_except_filters(only_options, except_options)
58
+ parse_filters(only_options) + parse_filters(except_options).map { |f| Filter::Not.new(f) }
59
+ end
60
+
52
61
  def join_filters(filters)
53
62
  filters.count > 1 ? Filter::And.new(filters) : filters.first
54
63
  end
55
64
 
56
- def parse_includes_filter(includes_options)
65
+ def includes_filter(includes_options)
57
66
  return [] if includes_options.blank?
58
67
 
59
68
  [Filter::Query.new(Elasticband::Query.parse(*includes_options))]
60
69
  end
61
70
 
62
- def parse_range_filter(range_options)
71
+ def range_filter(range_options)
63
72
  return [] if range_options.blank?
64
73
 
65
74
  [Filter::Range.new(range_options.keys.first, range_options.values.first)]
66
75
  end
67
76
 
77
+ def near_filter(options)
78
+ return [] if options.blank?
79
+
80
+ [Filter::Near.new(options)]
81
+ end
82
+
68
83
  def parse_filters(options)
69
84
  return [] if options.blank?
70
85
 
@@ -81,6 +81,14 @@ module Elasticband
81
81
  # function_score: {
82
82
  # query: ...,
83
83
  # gauss: { location: { origin: { lat: 12, lon: 34 }, offset: '5km', scale: '10km' } } } }
84
+ #
85
+ # Query.parse('foo', near: { on: :location, latitude: 12, longitude: 34, distance: '5km' })
86
+ # => {
87
+ # filtered: {
88
+ # query: ...,
89
+ # filter: { geo_distance: { location: { lat: 12, lon: 34 } }, distance: '5km' }
90
+ # }
91
+ # }
84
92
  # ```
85
93
  def parse(query_text, options = {})
86
94
  query = parse_on(query_text, options[:on])
@@ -1,3 +1,3 @@
1
1
  module Elasticband
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Elasticband::Filter::Near do
4
+ describe '#to_h' do
5
+ subject { described_class.new(options).to_h }
6
+
7
+ context 'with `:latidute` and `:latidute` option' do
8
+ let(:options) { { latitude: 12.5, longitude: -34.6 } }
9
+
10
+ it { is_expected.to eq(geo_distance: { location: { lat: 12.5, lon: -34.6 }, distance: '100km' }) }
11
+ end
12
+
13
+ context 'with `:on` option' do
14
+ let(:options) { { on: :loc, latitude: 12.5, longitude: -34.6 } }
15
+
16
+ it { is_expected.to eq(geo_distance: { loc: { lat: 12.5, lon: -34.6 }, distance: '100km' }) }
17
+ end
18
+
19
+ context 'with `:distance` option' do
20
+ let(:options) { { distance: '5km', latitude: 12.5, longitude: -34.6 } }
21
+
22
+ it { is_expected.to eq(geo_distance: { location: { lat: 12.5, lon: -34.6 }, distance: '5km' }) }
23
+ end
24
+ end
25
+ end
data/spec/filter_spec.rb CHANGED
@@ -97,5 +97,12 @@ RSpec.describe Elasticband::Filter do
97
97
  it { is_expected.to eq(range: { foo: { gt: 1, lt: 2 } }) }
98
98
  end
99
99
  end
100
+
101
+ context 'with `:near` option' do
102
+ let(:options) { { near: { on: :location, latitude: 12.5, longitude: -34.9, distance: '5km' } } }
103
+ let(:filter) { { geo_distance: { location: { lat: 12.5, lon: -34.9 }, distance: '5km' } } }
104
+
105
+ it { is_expected.to eq(filter) }
106
+ end
100
107
  end
101
108
  end
data/spec/query_spec.rb CHANGED
@@ -260,6 +260,17 @@ RSpec.describe Elasticband::Query do
260
260
  )
261
261
  end
262
262
  end
263
+
264
+ context 'with near option' do
265
+ let(:options) { { near: { on: :location, latitude: 12.5, longitude: -34.9, distance: '5km' } } }
266
+
267
+ let(:query) { { match: { _all: 'foo' } } }
268
+ let(:filter) { { geo_distance: { location: { lat: 12.5, lon: -34.9 }, distance: '5km' } } }
269
+
270
+ it 'return a filtered query by geo_distance' do
271
+ is_expected.to eq(filtered: { query: query, filter: filter })
272
+ end
273
+ end
263
274
  end
264
275
  end
265
276
  end
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.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Glauber Campinho
@@ -123,6 +123,7 @@ files:
123
123
  - lib/elasticband/aggregation/top_hits.rb
124
124
  - lib/elasticband/filter.rb
125
125
  - lib/elasticband/filter/and.rb
126
+ - lib/elasticband/filter/near.rb
126
127
  - lib/elasticband/filter/not.rb
127
128
  - lib/elasticband/filter/query.rb
128
129
  - lib/elasticband/filter/range.rb
@@ -153,6 +154,7 @@ files:
153
154
  - spec/aggregation/top_hits_spec.rb
154
155
  - spec/aggregation_spec.rb
155
156
  - spec/filter/and_spec.rb
157
+ - spec/filter/near_spec.rb
156
158
  - spec/filter/not_spec.rb
157
159
  - spec/filter/query_spec.rb
158
160
  - spec/filter/range_spec.rb