elasticband 0.1.0 → 0.1.1
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 +4 -4
- data/lib/elasticband/query.rb +33 -13
- data/lib/elasticband/version.rb +1 -1
- data/spec/query_spec.rb +42 -0
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae34274114e94681aaa9b43e5640f314bf265193
|
4
|
+
data.tar.gz: 1406a12e82fada6ad971a853248906aad2166999
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 61d9b27b7468403e5591395db6000f157881775d905465600e0ff04d5f2cdfa88a8f26a48da3a808d4565e0d56b356212dbb0462e24f88992c1bff213187d98a
|
7
|
+
data.tar.gz: b7064257bbc7bae491c156120da453715d29216ff75eadb451c2f7a55823f0c615ad41e90312d9be84940ea8db704fe8847c01b71f231ec73fe5deaed9e29e0c
|
data/lib/elasticband/query.rb
CHANGED
@@ -18,10 +18,12 @@ module Elasticband
|
|
18
18
|
# * `on:` Defines which attributes will searched in documents
|
19
19
|
# * `only:` Filter the search results where the condition is `true`
|
20
20
|
# * `except`: Filter the search results where the condition is `false`.
|
21
|
+
# * `includes:` Filter the search results with a `Match` query.
|
21
22
|
# * `boost_by:` Boosts the score of a query result based on a attribute of the document.
|
22
23
|
# This score will be multiplied for the `boost_by` attribute over function `ln2p`.
|
23
24
|
# * `boost_where:` Boosts the score of a query result where some condition is `true`.
|
24
25
|
# This score will be multiplied by 1000 (arbitrary, based on gem `searchkick`)
|
26
|
+
# * `boost_function:` Boosts using the function passed.
|
25
27
|
#
|
26
28
|
# #### Examples
|
27
29
|
# ```
|
@@ -40,9 +42,15 @@ module Elasticband
|
|
40
42
|
# Query.parse('foo', except: { company: { id: 1 } })
|
41
43
|
# => { filtered: { query: ..., filter: { not: { term: { status: :published } } } } }
|
42
44
|
#
|
45
|
+
# Query.parse('foo', includes: ['company', on: :description])
|
46
|
+
# => { filtered: { query: ..., filter: { query: { match: { description: 'company' } } } } }
|
47
|
+
#
|
43
48
|
# Query.parse('foo', boost_by: :contents_count)
|
44
49
|
# => { function_score: { query: ..., field_value_factor: { field: :contents_count, modifier: :ln2p } } }
|
45
50
|
#
|
51
|
+
# Query.parse('foo', boost_function: "_score * doc['users_count'].value")
|
52
|
+
# => { function_score: { query: ..., script_score: { script: '_score * doc['users_count'].value' } } }
|
53
|
+
#
|
46
54
|
# Query.parse('foo', boost_where: { company: { id: 1 } })
|
47
55
|
# => {
|
48
56
|
# function_score: {
|
@@ -55,8 +63,8 @@ module Elasticband
|
|
55
63
|
# ```
|
56
64
|
def parse(query_text, options = {})
|
57
65
|
query = parse_on(query_text, options[:on])
|
58
|
-
query =
|
59
|
-
query = parse_boost(query, options
|
66
|
+
query = parse_query_filters(query, options.slice(:only, :except, :includes))
|
67
|
+
query = parse_boost(query, options.slice(:boost_by, :boost_where, :boost_function))
|
60
68
|
query.to_h
|
61
69
|
end
|
62
70
|
|
@@ -73,6 +81,8 @@ module Elasticband
|
|
73
81
|
end
|
74
82
|
|
75
83
|
def parse_on(query_text, on_options)
|
84
|
+
return Query.new if query_text.blank?
|
85
|
+
|
76
86
|
if on_options.is_a?(Enumerable)
|
77
87
|
Query::MultiMatch.new(query_text, on_options)
|
78
88
|
else
|
@@ -80,10 +90,12 @@ module Elasticband
|
|
80
90
|
end
|
81
91
|
end
|
82
92
|
|
83
|
-
def
|
84
|
-
return query if
|
93
|
+
def parse_query_filters(query, filter_options)
|
94
|
+
return query if filter_options.blank?
|
85
95
|
|
86
|
-
filter = parse_filters(
|
96
|
+
filter = parse_filters(filter_options[:only])
|
97
|
+
filter += parse_filters(filter_options[:except]).map { |f| Filter::Not.new(f) }
|
98
|
+
filter += parse_includes_filter(filter_options[:includes])
|
87
99
|
filter = join_filters(filter)
|
88
100
|
|
89
101
|
Query::Filtered.new(filter, query)
|
@@ -93,6 +105,12 @@ module Elasticband
|
|
93
105
|
filters.count > 1 ? Filter::And.new(filters) : filters.first
|
94
106
|
end
|
95
107
|
|
108
|
+
def parse_includes_filter(includes_options)
|
109
|
+
return [] if includes_options.blank?
|
110
|
+
|
111
|
+
[Filter::Query.new(parse(*includes_options))]
|
112
|
+
end
|
113
|
+
|
96
114
|
def parse_filters(options)
|
97
115
|
return [] if options.blank?
|
98
116
|
|
@@ -107,19 +125,21 @@ module Elasticband
|
|
107
125
|
end
|
108
126
|
end
|
109
127
|
|
110
|
-
def parse_boost(query,
|
111
|
-
return query if
|
128
|
+
def parse_boost(query, boost_options)
|
129
|
+
return query if boost_options.blank?
|
112
130
|
|
113
|
-
function = parse_boost_function(
|
131
|
+
function = parse_boost_function(boost_options)
|
114
132
|
Query::FunctionScore.new(query, function)
|
115
133
|
end
|
116
134
|
|
117
|
-
def parse_boost_function(
|
118
|
-
if
|
119
|
-
ScoreFunction::FieldValueFactor.new(
|
120
|
-
|
121
|
-
filter = join_filters(parse_filters(
|
135
|
+
def parse_boost_function(boost_options)
|
136
|
+
if boost_options[:boost_by].present?
|
137
|
+
ScoreFunction::FieldValueFactor.new(boost_options[:boost_by], modifier: :ln2p)
|
138
|
+
elsif boost_options[:boost_where].present?
|
139
|
+
filter = join_filters(parse_filters(boost_options[:boost_where]))
|
122
140
|
ScoreFunction::Filtered.new(filter, ScoreFunction::BoostFactor.new(1_000))
|
141
|
+
else
|
142
|
+
ScoreFunction::ScriptScore.new(boost_options[:boost_function])
|
123
143
|
end
|
124
144
|
end
|
125
145
|
end
|
data/lib/elasticband/version.rb
CHANGED
data/spec/query_spec.rb
CHANGED
@@ -8,6 +8,12 @@ RSpec.describe Elasticband::Query do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
describe '.parse' do
|
11
|
+
context 'with no query' do
|
12
|
+
subject { described_class.parse('') }
|
13
|
+
|
14
|
+
it { is_expected.to eq(match_all: {}) }
|
15
|
+
end
|
16
|
+
|
11
17
|
context 'with only the query text' do
|
12
18
|
subject { described_class.parse('foo') }
|
13
19
|
|
@@ -175,6 +181,27 @@ RSpec.describe Elasticband::Query do
|
|
175
181
|
end
|
176
182
|
end
|
177
183
|
|
184
|
+
context 'with `:includes` option' do
|
185
|
+
let(:options) { { includes: ['bar', on: :description] } }
|
186
|
+
|
187
|
+
it 'returns a filtered query with query filter' do
|
188
|
+
is_expected.to eq(
|
189
|
+
filtered: {
|
190
|
+
query: { match: { _all: 'foo' } },
|
191
|
+
filter: {
|
192
|
+
query: { match: { description: 'bar' } }
|
193
|
+
}
|
194
|
+
}
|
195
|
+
)
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'calls `.parse` for the includes option' do
|
199
|
+
allow(described_class).to receive(:parse).with('foo', options).and_call_original
|
200
|
+
expect(described_class).to receive(:parse).with('bar', on: :description).and_call_original
|
201
|
+
subject
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
178
205
|
context 'with `:boost_by` option' do
|
179
206
|
let(:options) { { boost_by: :contents_count } }
|
180
207
|
|
@@ -191,6 +218,21 @@ RSpec.describe Elasticband::Query do
|
|
191
218
|
end
|
192
219
|
end
|
193
220
|
|
221
|
+
context 'with `:boost_function` option' do
|
222
|
+
let(:options) { { boost_function: "_score * doc['users_count'].value" } }
|
223
|
+
|
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"
|
230
|
+
}
|
231
|
+
}
|
232
|
+
)
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
194
236
|
context 'with `:boost_where` option' do
|
195
237
|
context 'with a regular attribute' do
|
196
238
|
let(:options) { { boost_where: { status: :published } } }
|