elasticband 0.5.0 → 0.6.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 +8 -8
- data/.rubocop.yml +3 -0
- data/lib/elasticband/aggregation.rb +1 -1
- data/lib/elasticband/aggregation/field_based.rb +1 -1
- data/lib/elasticband/filter.rb +99 -88
- data/lib/elasticband/filter/exists.rb +15 -0
- data/lib/elasticband/filter/range.rb +1 -1
- data/lib/elasticband/query/score_function/boost_mode.rb +1 -1
- data/lib/elasticband/query/score_function/score_mode.rb +1 -1
- data/lib/elasticband/version.rb +1 -1
- data/spec/filter/exists_spec.rb +9 -0
- data/spec/filter_spec.rb +9 -2
- data/spec/query_spec.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YWVjNzAzOTVlY2JlZGI0NmE3ZTRjOTYzNDNjNWUwMzQzZGVmODVkZg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzJkYTMzMzQ5ODE5NWUyMDEyYTViNjg3OWYzNWIyMWE5MmRjMjg3MQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NjRlM2EwMWIyYzU0YzViYjM3OWNjNjRmNjg0M2ZhY2U4OGM3OWU0ZjYzM2Iy
|
10
|
+
MjcyZDE4N2IwMTEyZTVmNDlhMDQ2NDE5MDk3MDg0M2M4ZWE2NjYwYzAzYWMy
|
11
|
+
YTRmNjU2NTE5Y2Y2ZmY2NmQxN2Y5NWJiOGQ1NWY5MmY1OTVhNjg=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZGQxMjNiYzhjZjUxODdkMThmYjY3YTJkMDE3YmI1ZGE2MTU3NzYyMzQ0NDNi
|
14
|
+
M2Q2ZjE2YTBlODY4YzNkNWZhOTU3NmY5ZDcxNmRhZmY2YmRjZGM1ZTcxYzM5
|
15
|
+
NmNlZGIwODI0NmQ4NDU3MjFmYjBkYjFmMWYzNDRhN2UzYzM4M2I=
|
data/.rubocop.yml
CHANGED
@@ -7,7 +7,7 @@ require 'elasticband/aggregation/top_hits'
|
|
7
7
|
|
8
8
|
module Elasticband
|
9
9
|
class Aggregation
|
10
|
-
PARSE_AGGREGATIONS = %i(group_by group_max top_hits group_by_filter)
|
10
|
+
PARSE_AGGREGATIONS = %i(group_by group_max top_hits group_by_filter).freeze
|
11
11
|
|
12
12
|
attr_accessor :name
|
13
13
|
|
data/lib/elasticband/filter.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'elasticband/filter/and'
|
2
|
+
require 'elasticband/filter/exists'
|
2
3
|
require 'elasticband/filter/not'
|
3
4
|
require 'elasticband/filter/query'
|
4
5
|
require 'elasticband/filter/range'
|
@@ -9,117 +10,127 @@ require 'elasticband/filter/script'
|
|
9
10
|
|
10
11
|
module Elasticband
|
11
12
|
class Filter
|
12
|
-
PARSE_FILTERS = %i(only except includes range near)
|
13
|
+
PARSE_FILTERS = %i(only except exists includes range near).freeze
|
14
|
+
|
15
|
+
attr_reader :options
|
16
|
+
|
17
|
+
# Parses filter options to a Elasticsearch syntax
|
18
|
+
#
|
19
|
+
# #### Options
|
20
|
+
#
|
21
|
+
# * `only:` Filter the search results where the condition is `true`
|
22
|
+
# * `except`: Filter the search results where the condition is `false`.
|
23
|
+
# * `includes:` Filter the search results with a `Match` query.
|
24
|
+
# * `range:` Filter the search results where the condition is on the given range.
|
25
|
+
# * `near:` Filter the search results where the results are near a geo point.
|
26
|
+
# * `script:` Filter the search results where the results match the script.
|
27
|
+
#
|
28
|
+
# #### Examples
|
29
|
+
# ```
|
30
|
+
# Filter.parse(only: { status: :published })
|
31
|
+
# => { term: { status: :published } }
|
32
|
+
#
|
33
|
+
# Filter.parse(exists: :status)
|
34
|
+
# => { exists: { field: :status } }
|
35
|
+
#
|
36
|
+
# Filter.parse(except: { company: { id: 1 } })
|
37
|
+
# => { not: { term: { status: :published } } }
|
38
|
+
#
|
39
|
+
# Filter.parse(includes: ['company', on: :description])
|
40
|
+
# => { query: { match: { description: 'company' } } }
|
41
|
+
#
|
42
|
+
# Filter.parse(range: { companies_count: { gt: 1, gteq: 1, lt: 1, lteq: 1 } })
|
43
|
+
# => { range: { companies_count: { gt: 1, gte: 1, lt: 1, lte: 1 } } }
|
44
|
+
#
|
45
|
+
# Filter.parse(near: { latitude: 12, longitude: 34, distance: '5km', type: :arc })
|
46
|
+
# => { geo_distance: { location: { lat: 12, lon: 34 } }, distance: '5km', distance_type: :arc }
|
47
|
+
#
|
48
|
+
# Filter.parse(script: ['(param1 + param2) > 0', param1: 1, param2: 1])
|
49
|
+
# => { script: { script: '(param1 + param2) > 0', params: { param1: 1, param2: 1 } } }
|
50
|
+
# ```
|
51
|
+
|
52
|
+
def self.parse(options = {})
|
53
|
+
new(options).parse
|
54
|
+
end
|
55
|
+
|
56
|
+
def initialize(options = {})
|
57
|
+
@options = options
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse
|
61
|
+
return {} if options.blank?
|
62
|
+
|
63
|
+
join_filters(filters).to_h
|
64
|
+
end
|
13
65
|
|
14
66
|
def to_h
|
15
67
|
{ match_all: {} }
|
16
68
|
end
|
17
69
|
|
18
|
-
|
19
|
-
# Parses filter options to a Elasticsearch syntax
|
20
|
-
#
|
21
|
-
# #### Options
|
22
|
-
#
|
23
|
-
# * `only:` Filter the search results where the condition is `true`
|
24
|
-
# * `except`: Filter the search results where the condition is `false`.
|
25
|
-
# * `includes:` Filter the search results with a `Match` query.
|
26
|
-
# * `range:` Filter the search results where the condition is on the given range.
|
27
|
-
# * `near:` Filter the search results where the results are near a geo point.
|
28
|
-
# * `script:` Filter the search results where the results match the script.
|
29
|
-
#
|
30
|
-
# #### Examples
|
31
|
-
# ```
|
32
|
-
# Filter.parse(only: { status: :published })
|
33
|
-
# => { term: { status: :published } }
|
34
|
-
#
|
35
|
-
# Filter.parse(except: { company: { id: 1 } })
|
36
|
-
# => { not: { term: { status: :published } } }
|
37
|
-
#
|
38
|
-
# Filter.parse(includes: ['company', on: :description])
|
39
|
-
# => { query: { match: { description: 'company' } } }
|
40
|
-
#
|
41
|
-
# Filter.parse(range: { companies_count: { gt: 1, gteq: 1, lt: 1, lteq: 1 } })
|
42
|
-
# => { range: { companies_count: { gt: 1, gte: 1, lt: 1, lte: 1 } } }
|
43
|
-
#
|
44
|
-
# Filter.parse(near: { latitude: 12, longitude: 34, distance: '5km', type: :arc })
|
45
|
-
# => { geo_distance: { location: { lat: 12, lon: 34 } }, distance: '5km', distance_type: :arc }
|
46
|
-
#
|
47
|
-
# Filter.parse(script: ['(param1 + param2) > 0', param1: 1, param2: 1])
|
48
|
-
# => { script: { script: '(param1 + param2) > 0', params: { param1: 1, param2: 1 } } }
|
49
|
-
# ```
|
50
|
-
def parse(options = {})
|
51
|
-
return {} if options.blank?
|
52
|
-
|
53
|
-
filters = map_filters(options)
|
54
|
-
|
55
|
-
join_filters(filters).to_h
|
56
|
-
end
|
70
|
+
private
|
57
71
|
|
58
|
-
|
72
|
+
def filters
|
73
|
+
only_and_except_filters + exists_filter + includes_filter + range_filter + near_filter + script_filter
|
74
|
+
end
|
59
75
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
filters += range_filter(options[:range])
|
64
|
-
filters += near_filter(options[:near])
|
65
|
-
filters += script_filter(options[:script])
|
76
|
+
def only_and_except_filters
|
77
|
+
parse_filters(options[:only]) + parse_filters(options[:except]).map { |f| Filter::Not.new(f) }
|
78
|
+
end
|
66
79
|
|
67
|
-
|
68
|
-
|
80
|
+
def exists_filter
|
81
|
+
return [] if options[:exists].blank?
|
69
82
|
|
70
|
-
|
71
|
-
|
72
|
-
end
|
83
|
+
[Filter::Exists.new(options[:exists])]
|
84
|
+
end
|
73
85
|
|
74
|
-
|
75
|
-
|
76
|
-
|
86
|
+
def includes_filter
|
87
|
+
return [] if options[:includes].blank?
|
88
|
+
|
89
|
+
[Filter::Query.new(Elasticband::Query.parse(*options[:includes]))]
|
90
|
+
end
|
77
91
|
|
78
|
-
|
79
|
-
|
92
|
+
def range_filter
|
93
|
+
return [] if options[:range].blank?
|
80
94
|
|
81
|
-
|
82
|
-
|
95
|
+
[Filter::Range.new(options[:range].keys.first, options[:range].values.first)]
|
96
|
+
end
|
83
97
|
|
84
|
-
|
85
|
-
|
98
|
+
def join_filters(filters)
|
99
|
+
filters.count > 1 ? Filter::And.new(filters) : filters.first
|
100
|
+
end
|
86
101
|
|
87
|
-
|
88
|
-
|
102
|
+
def near_filter
|
103
|
+
return [] if options[:near].blank?
|
89
104
|
|
90
|
-
|
91
|
-
|
105
|
+
[Filter::Near.new(options[:near])]
|
106
|
+
end
|
92
107
|
|
93
|
-
|
94
|
-
|
108
|
+
def script_filter
|
109
|
+
return [] if options[:script].blank?
|
95
110
|
|
96
|
-
|
97
|
-
|
111
|
+
[Filter::Script.new(*options[:script])]
|
112
|
+
end
|
98
113
|
|
99
|
-
|
100
|
-
|
114
|
+
def parse_filters(filter)
|
115
|
+
return [] if filter.blank?
|
101
116
|
|
102
|
-
|
103
|
-
|
117
|
+
to_dotted_notation(filter).map { |attribute, value| parse_filter(attribute, value) }
|
118
|
+
end
|
104
119
|
|
105
|
-
|
120
|
+
def parse_filter(attribute, value)
|
121
|
+
if value.is_a?(Enumerable)
|
122
|
+
Filter::Terms.new(value, attribute)
|
123
|
+
else
|
124
|
+
Filter::Term.new(value, attribute)
|
106
125
|
end
|
126
|
+
end
|
107
127
|
|
108
|
-
|
109
|
-
|
110
|
-
|
128
|
+
def to_dotted_notation(hash_params, prefix = nil, dotted_hash = {})
|
129
|
+
hash_params.each_with_object(dotted_hash) do |(key, val), hash|
|
130
|
+
if val.is_a?(Hash)
|
131
|
+
to_dotted_notation(val, "#{prefix}#{key}.", hash)
|
111
132
|
else
|
112
|
-
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def to_dotted_notation(hash_params, prefix = nil, dotted_hash = {})
|
117
|
-
hash_params.each_with_object(dotted_hash) do |(key, val), hash|
|
118
|
-
if val.is_a?(Hash)
|
119
|
-
to_dotted_notation(val, "#{prefix}#{key}.", hash)
|
120
|
-
else
|
121
|
-
hash["#{prefix}#{key}"] = val
|
122
|
-
end
|
133
|
+
hash["#{prefix}#{key}"] = val
|
123
134
|
end
|
124
135
|
end
|
125
136
|
end
|
data/lib/elasticband/version.rb
CHANGED
data/spec/filter_spec.rb
CHANGED
@@ -27,7 +27,7 @@ RSpec.describe Elasticband::Filter do
|
|
27
27
|
context 'with a nested attribute' do
|
28
28
|
let(:options) { { only: { company: { id: 1 } } } }
|
29
29
|
|
30
|
-
it { is_expected.to eq(term: { 'company.id'
|
30
|
+
it { is_expected.to eq(term: { :'company.id' => 1 }) }
|
31
31
|
end
|
32
32
|
|
33
33
|
context 'with multiple values' do
|
@@ -57,7 +57,7 @@ RSpec.describe Elasticband::Filter do
|
|
57
57
|
context 'with a nested attribute' do
|
58
58
|
let(:options) { { except: { company: { id: 1 } } } }
|
59
59
|
|
60
|
-
it { is_expected.to eq(not: { term: { 'company.id'
|
60
|
+
it { is_expected.to eq(not: { term: { :'company.id' => 1 } }) }
|
61
61
|
end
|
62
62
|
|
63
63
|
context 'with multiple values' do
|
@@ -107,6 +107,13 @@ RSpec.describe Elasticband::Filter do
|
|
107
107
|
it { is_expected.to eq(filter) }
|
108
108
|
end
|
109
109
|
|
110
|
+
context 'with `:exists` option' do
|
111
|
+
let(:options) { { exists: :user } }
|
112
|
+
let(:filter) { { exists: { field: :user } } }
|
113
|
+
|
114
|
+
it { is_expected.to eq(filter) }
|
115
|
+
end
|
116
|
+
|
110
117
|
context 'with `:script` option' do
|
111
118
|
let(:options) { { script: ['(param1 + param2) > 0', param1: 1, param2: 1] } }
|
112
119
|
let(:filter) { { script: { script: '(param1 + param2) > 0', params: { param1: 1, param2: 1 } } } }
|
data/spec/query_spec.rb
CHANGED
@@ -39,7 +39,7 @@ RSpec.describe Elasticband::Query do
|
|
39
39
|
context 'with a composed name on `:on` option' do
|
40
40
|
let(:options) { { on: 'company.name' } }
|
41
41
|
|
42
|
-
it { is_expected.to eq(match: { 'company.name'
|
42
|
+
it { is_expected.to eq(match: { :'company.name' => 'foo' }) }
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
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.
|
4
|
+
version: 0.6.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/exists.rb
|
126
127
|
- lib/elasticband/filter/near.rb
|
127
128
|
- lib/elasticband/filter/not.rb
|
128
129
|
- lib/elasticband/filter/query.rb
|
@@ -155,6 +156,7 @@ files:
|
|
155
156
|
- spec/aggregation/top_hits_spec.rb
|
156
157
|
- spec/aggregation_spec.rb
|
157
158
|
- spec/filter/and_spec.rb
|
159
|
+
- spec/filter/exists_spec.rb
|
158
160
|
- spec/filter/near_spec.rb
|
159
161
|
- spec/filter/not_spec.rb
|
160
162
|
- spec/filter/query_spec.rb
|