stretchy 0.4.6 → 0.4.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.editorconfig +12 -0
- data/CONTRIBUTING.md +52 -0
- data/README.md +157 -40
- data/lib/stretchy/builders/filter_builder.rb +12 -7
- data/lib/stretchy/builders/query_builder.rb +1 -1
- data/lib/stretchy/builders/where_builder.rb +7 -3
- data/lib/stretchy/clauses/base.rb +63 -57
- data/lib/stretchy/clauses/boost_clause.rb +47 -49
- data/lib/stretchy/clauses/boost_match_clause.rb +52 -19
- data/lib/stretchy/clauses/boost_where_clause.rb +46 -28
- data/lib/stretchy/clauses/match_clause.rb +52 -42
- data/lib/stretchy/clauses/where_clause.rb +86 -70
- data/lib/stretchy/filters/params_filter.rb +27 -0
- data/lib/stretchy/filters.rb +1 -0
- data/lib/stretchy/queries/params_query.rb +21 -0
- data/lib/stretchy/queries.rb +1 -0
- data/lib/stretchy/version.rb +1 -1
- metadata +6 -2
@@ -2,37 +2,34 @@ require 'stretchy/clauses/base'
|
|
2
2
|
|
3
3
|
module Stretchy
|
4
4
|
module Clauses
|
5
|
-
#
|
6
|
-
# A Where clause inherits the same state as any clause,
|
5
|
+
#
|
6
|
+
# A Where clause inherits the same state as any clause,
|
7
7
|
# but has a few possible states to transition to. You
|
8
8
|
# can call {#range} and {#geo} to add their respective
|
9
9
|
# filters, or you can transition to the inverted state
|
10
10
|
# via {#not}, or the `should` state via {#should}
|
11
|
-
#
|
11
|
+
#
|
12
12
|
# ### STATES:
|
13
13
|
# * **inverted:** any filters added in this state will be
|
14
14
|
# inverted, ie the document must **NOT** match said
|
15
15
|
# filters.
|
16
16
|
# * **should:** any filters added in this state will be
|
17
17
|
# applied to a `should` block. Documents which do
|
18
|
-
# not match these filters will be returned, but
|
19
|
-
# documents which do match will have a higher
|
18
|
+
# not match these filters will be returned, but
|
19
|
+
# documents which do match will have a higher
|
20
20
|
# relevance score.
|
21
|
-
#
|
21
|
+
#
|
22
22
|
# @author [atevans]
|
23
|
-
#
|
23
|
+
#
|
24
24
|
class WhereClause < Base
|
25
25
|
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
# @param base [Base] Used to intialize the new state from the previous clause
|
26
|
+
#
|
27
|
+
# Add term-style filters to the query. This is similar to ActiveRecord's `where`
|
28
|
+
# method. Also exits any should or inverse state. To add terms to those states,
|
29
|
+
# chain the `.should` or `.not` methods after this one.
|
30
|
+
#
|
32
31
|
# @param params = {} [Hash] filters to be applied to the new state
|
33
|
-
#
|
34
|
-
# @option params [true, false] :should (nil) Whether the new state is should
|
35
|
-
#
|
32
|
+
#
|
36
33
|
# @example Apply ActiveRecord-like filters
|
37
34
|
# query.where(
|
38
35
|
# string_field: "string",
|
@@ -40,13 +37,18 @@ module Stretchy
|
|
40
37
|
# in_range: 27..33,
|
41
38
|
# included_in: [47, 23, 86]
|
42
39
|
# )
|
43
|
-
#
|
40
|
+
#
|
41
|
+
# @example Apply should filters
|
42
|
+
# query.where.should(
|
43
|
+
# string_field: "string"
|
44
|
+
# )
|
45
|
+
#
|
44
46
|
# @see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-filter.html Elastic Docs - Terms Filter
|
45
|
-
#
|
47
|
+
#
|
46
48
|
# @see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-filter.html Elastic Docs - Exists Filter
|
47
|
-
#
|
49
|
+
#
|
48
50
|
# @see http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-filter.html Elastic Docs - Range Filter
|
49
|
-
#
|
51
|
+
#
|
50
52
|
def where(params = {}, options = {})
|
51
53
|
@inverse = false
|
52
54
|
@should = false
|
@@ -54,58 +56,73 @@ module Stretchy
|
|
54
56
|
self
|
55
57
|
end
|
56
58
|
|
57
|
-
#
|
59
|
+
#
|
60
|
+
# Add arbitrary json as a filter in the appropriate context.
|
61
|
+
# This can be used to add filters that are not currently supported
|
62
|
+
# by Stretchy to be used in the final query.
|
63
|
+
#
|
64
|
+
# @param params = {} [Hash] Filter to be applied to the new state
|
65
|
+
# @option options [true, false] :inverse (nil) Ignore query state and add to the `not` filters
|
66
|
+
# @option options [true, false] :should (nil) Ignore query state and add to the `should` filters
|
67
|
+
def filter(params, options = {})
|
68
|
+
base.where_builder.add_filter(
|
69
|
+
Filters::ParamsFilter.new(params),
|
70
|
+
merge_state(options)
|
71
|
+
)
|
72
|
+
self
|
73
|
+
end
|
74
|
+
|
75
|
+
#
|
58
76
|
# Accessor for `@should`
|
59
|
-
#
|
77
|
+
#
|
60
78
|
# @return [true, false] `@should`
|
61
79
|
def should?
|
62
80
|
!!@should
|
63
81
|
end
|
64
82
|
|
65
|
-
#
|
83
|
+
#
|
66
84
|
# Add a range filter to the current context. While
|
67
85
|
# you can pass a `Range` object to {#where}, this
|
68
86
|
# allows you to specify an open-ended range, such
|
69
87
|
# as only specifying the minimum or maximum value.
|
70
|
-
#
|
88
|
+
#
|
71
89
|
# @param field [String, Symbol] The field to filter with this range
|
72
90
|
# @param options = {} [Hash] Options for the range
|
73
91
|
# @option options [Numeric] :min (nil) Minimum. Ranges are _inclusive_ by default
|
74
92
|
# @option options [Numeric] :max (nil) Maximum. Ranges are _inclusive_ by default
|
75
|
-
# @option options [true, false] :exclusive (nil) Overrides default and makes the range exclusive -
|
93
|
+
# @option options [true, false] :exclusive (nil) Overrides default and makes the range exclusive -
|
76
94
|
# equivalent to passing both `:exclusive_min` and `:exclusive_max`
|
77
95
|
# @option options [true, false] :exclusive_min (nil) Overrides default and makes the minimum exclusive
|
78
96
|
# @option options [true, false] :exclusive_max (nil) Overrides default and makes the maximum exclusive
|
79
|
-
#
|
97
|
+
#
|
80
98
|
# @return [self] query state with range filter applied
|
81
|
-
#
|
99
|
+
#
|
82
100
|
# @example Adding a range filter
|
83
101
|
# query.where.range(:my_range_field,
|
84
102
|
# min: 33,
|
85
103
|
# exclusive: true
|
86
104
|
# )
|
87
105
|
def range(field, options = {})
|
88
|
-
options
|
89
|
-
options[:should] = true if should?
|
106
|
+
options = merge_state(options)
|
90
107
|
base.where_builder.add_range(field, options)
|
91
108
|
self
|
92
109
|
end
|
93
110
|
|
94
|
-
#
|
111
|
+
#
|
95
112
|
# Adds a geo distance filter to the current context.
|
96
113
|
# Documents must have a `geo_point` field that is within
|
97
114
|
# the specified distance of the passed parameters.
|
98
|
-
#
|
115
|
+
#
|
99
116
|
# @param field [String, Symbol] The field this filter will be applied to.
|
100
117
|
# @param options = {} [Hash] Options for the geo distance filter
|
101
|
-
# @option options [String] :distance (nil) The maximum distance from the specified origin.
|
118
|
+
# @option options [String] :distance (nil) The maximum distance from the specified origin.
|
102
119
|
# Use an Elastic distance format such as `'21mi'` or `'37km'`
|
103
120
|
# @option options [Float] :lat (nil) The latitude of the origin point. Can also be specified as `:latitude`
|
104
|
-
# @option options [Float] :lng (nil) The longitude of the origin point.
|
121
|
+
# @option options [Float] :lng (nil) The longitude of the origin point.
|
105
122
|
# Can also be specified as `:lon` or `:longitude`
|
106
|
-
#
|
123
|
+
#
|
107
124
|
# @return [self] query state with geo distance filter applied
|
108
|
-
#
|
125
|
+
#
|
109
126
|
# @example Searching by distance from a point
|
110
127
|
# query.where.geo(:coords,
|
111
128
|
# distance: '27km',
|
@@ -114,50 +131,49 @@ module Stretchy
|
|
114
131
|
# )
|
115
132
|
def geo(field, options = {})
|
116
133
|
distance = options[:distance]
|
117
|
-
options
|
118
|
-
options[:should] = true if should?
|
134
|
+
options = merge_state(options)
|
119
135
|
base.where_builder.add_geo(field, distance, options)
|
120
136
|
self
|
121
137
|
end
|
122
138
|
|
123
|
-
#
|
139
|
+
#
|
124
140
|
# Used for passing strings or symbols in a `.where`
|
125
141
|
# method, and using the un-analyzed Terms filter instead
|
126
142
|
# of an analyzed and parsed Match Query.
|
127
|
-
#
|
143
|
+
#
|
128
144
|
# This would be useful if you have a set of specific
|
129
145
|
# strings a field could be in, such as:
|
130
146
|
# `role: ['admin_user', 'company_manager']`
|
131
147
|
# and you want to query for those exact strings without
|
132
148
|
# the usual downcase / punctuation removal analysis.
|
133
|
-
#
|
149
|
+
#
|
134
150
|
# **CAUTION:** The keys indexed by elastic may be analyzed -
|
135
151
|
# downcased, punctuation removed, etc. Using a terms filter
|
136
152
|
# in this case _will not work_ . Hence the default of using
|
137
153
|
# a match query for strings and symbols instead.
|
138
|
-
#
|
139
|
-
# @param options = {} [Hash] Options to be passed to the
|
154
|
+
#
|
155
|
+
# @param options = {} [Hash] Options to be passed to the
|
140
156
|
# {WhereClause}
|
141
|
-
#
|
157
|
+
#
|
142
158
|
# @return [WhereClause] query state with filters applied
|
143
|
-
#
|
159
|
+
#
|
144
160
|
# @example Querying for exact terms
|
145
161
|
# query.where.terms(
|
146
162
|
# status_field: 'working_fine_today',
|
147
163
|
# number: 27,
|
148
164
|
# date: Date.today
|
149
165
|
# )
|
150
|
-
#
|
166
|
+
#
|
151
167
|
# @example Not matching exact terms
|
152
168
|
# query.where.not.terms(
|
153
169
|
# email: 'my.email@company.com'
|
154
170
|
# )
|
155
|
-
#
|
171
|
+
#
|
156
172
|
# @example Should match exact terms
|
157
173
|
# query.should.terms(
|
158
174
|
# hacker_alias: '!!ic3y.h0t~~!'
|
159
175
|
# )
|
160
|
-
#
|
176
|
+
#
|
161
177
|
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-filter.html Elasticsearch Terms Filter
|
162
178
|
def terms(params = {}, options = {})
|
163
179
|
options[:exact] = true
|
@@ -166,17 +182,17 @@ module Stretchy
|
|
166
182
|
end
|
167
183
|
alias :exact :terms
|
168
184
|
|
169
|
-
#
|
170
|
-
# Switches current state to inverted. Options passed
|
185
|
+
#
|
186
|
+
# Switches current state to inverted. Options passed
|
171
187
|
# here are equivalent to those passed to {#initialize},
|
172
188
|
# except documents *must not* match these filters.
|
173
|
-
#
|
189
|
+
#
|
174
190
|
# Can be chained with {#should} to produce inverted should queries
|
175
|
-
#
|
191
|
+
#
|
176
192
|
# @param params = {} [Hash] params to filter on
|
177
|
-
#
|
193
|
+
#
|
178
194
|
# @return [WhereClause] inverted query state with not filters applied.
|
179
|
-
#
|
195
|
+
#
|
180
196
|
# @example Inverting filters
|
181
197
|
# query.where.not(
|
182
198
|
# must_exist: nil,
|
@@ -184,7 +200,7 @@ module Stretchy
|
|
184
200
|
# not_in: [45, 67, 99],
|
185
201
|
# not_in_range: 89..23
|
186
202
|
# )
|
187
|
-
#
|
203
|
+
#
|
188
204
|
# @example Inverted should filters
|
189
205
|
# query.should.not(
|
190
206
|
# match_field: [:these, "params"]
|
@@ -195,31 +211,31 @@ module Stretchy
|
|
195
211
|
self
|
196
212
|
end
|
197
213
|
|
198
|
-
#
|
214
|
+
#
|
199
215
|
# Switches the current state to `should`. Options passed
|
200
216
|
# here are equivalent to those passed to {#initialize},
|
201
217
|
# except documents which do not match are still returned
|
202
218
|
# with a lower score than documents which do match.
|
203
|
-
#
|
219
|
+
#
|
204
220
|
# Can be chained with {#not} to produce inverted should queries
|
205
|
-
#
|
221
|
+
#
|
206
222
|
# **CAUTION:** Documents that don't match at least one `should`
|
207
223
|
# clause will not be returned.
|
208
|
-
#
|
224
|
+
#
|
209
225
|
# @param params = {} [Hash] params to filter on
|
210
|
-
#
|
226
|
+
#
|
211
227
|
# @return [WhereClause] should query state with should filters applied
|
212
|
-
#
|
228
|
+
#
|
213
229
|
# @example Specifying should params
|
214
230
|
# query.should(
|
215
231
|
# field: [99, 27]
|
216
232
|
# )
|
217
|
-
#
|
233
|
+
#
|
218
234
|
# @example Inverted should params
|
219
235
|
# query.should.not(
|
220
236
|
# exists_field: nil
|
221
|
-
# )
|
222
|
-
#
|
237
|
+
# )
|
238
|
+
#
|
223
239
|
# @see https://www.elastic.co/guide/en/elasticsearch/reference/1.4/query-dsl-bool-query.html Elasticsearch Bool Query docs (bool filter just references this)
|
224
240
|
def should(params = {}, options = {})
|
225
241
|
@inverse = false
|
@@ -228,12 +244,12 @@ module Stretchy
|
|
228
244
|
self
|
229
245
|
end
|
230
246
|
|
231
|
-
#
|
247
|
+
#
|
232
248
|
# Converts the current context into a boost to
|
233
249
|
# be passed into a {FunctionScoreQuery}.
|
234
|
-
#
|
250
|
+
#
|
235
251
|
# @param weight = nil [Numeric] A weight for the {FunctionScoreQuery}
|
236
|
-
#
|
252
|
+
#
|
237
253
|
# @return [Boosts::FilterBoost] A boost including all the current filters
|
238
254
|
def to_boost(weight = nil)
|
239
255
|
weight ||= Stretchy::Boosts::FilterBoost::DEFAULT_WEIGHT
|
@@ -248,7 +264,7 @@ module Stretchy
|
|
248
264
|
),
|
249
265
|
weight: weight
|
250
266
|
)
|
251
|
-
|
267
|
+
|
252
268
|
elsif base.match_builder.any?
|
253
269
|
Stretchy::Boosts::FilterBoost.new(
|
254
270
|
filter: Stretchy::Filters::QueryFilter.new(
|
@@ -266,13 +282,13 @@ module Stretchy
|
|
266
282
|
end
|
267
283
|
|
268
284
|
private
|
269
|
-
|
285
|
+
|
270
286
|
def add_params(params = {}, options = {})
|
271
287
|
params.each do |field, param|
|
272
288
|
# if it is an array, process each param
|
273
289
|
# separately - ensures string & symbols
|
274
290
|
# always go into .match_builder
|
275
|
-
|
291
|
+
|
276
292
|
if param.is_a?(Array)
|
277
293
|
param.each{|p| add_param(field, p, options) }
|
278
294
|
else
|
@@ -295,4 +311,4 @@ module Stretchy
|
|
295
311
|
|
296
312
|
end
|
297
313
|
end
|
298
|
-
end
|
314
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'stretchy/filters/base'
|
2
|
+
|
3
|
+
module Stretchy
|
4
|
+
module Filters
|
5
|
+
|
6
|
+
# This class allows using arbitrary JSON as a filter.
|
7
|
+
# This way, users can make use of elasticsearch features
|
8
|
+
# not yet supported by Stretchy
|
9
|
+
|
10
|
+
class ParamsFilter < Base
|
11
|
+
|
12
|
+
attribute :params, Hash
|
13
|
+
|
14
|
+
validations do
|
15
|
+
rule :params, :required
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(params)
|
19
|
+
@params = params
|
20
|
+
validate!
|
21
|
+
end
|
22
|
+
|
23
|
+
alias :to_search :params
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/stretchy/filters.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'stretchy/queries/base'
|
2
|
+
|
3
|
+
module Stretchy
|
4
|
+
module Queries
|
5
|
+
class ParamsQuery < Base
|
6
|
+
|
7
|
+
attribute :params, Hash
|
8
|
+
|
9
|
+
validations do
|
10
|
+
rule :params, :required
|
11
|
+
end
|
12
|
+
|
13
|
+
def initialize(params)
|
14
|
+
@params = params
|
15
|
+
end
|
16
|
+
|
17
|
+
alias :to_search :params
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/stretchy/queries.rb
CHANGED
data/lib/stretchy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stretchy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- agius
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: elasticsearch
|
@@ -171,9 +171,11 @@ executables: []
|
|
171
171
|
extensions: []
|
172
172
|
extra_rdoc_files: []
|
173
173
|
files:
|
174
|
+
- ".editorconfig"
|
174
175
|
- ".gitignore"
|
175
176
|
- ".ruby-version"
|
176
177
|
- ".yardopts"
|
178
|
+
- CONTRIBUTING.md
|
177
179
|
- Gemfile
|
178
180
|
- README.md
|
179
181
|
- Rakefile
|
@@ -211,6 +213,7 @@ files:
|
|
211
213
|
- lib/stretchy/filters/geo_filter.rb
|
212
214
|
- lib/stretchy/filters/not_filter.rb
|
213
215
|
- lib/stretchy/filters/or_filter.rb
|
216
|
+
- lib/stretchy/filters/params_filter.rb
|
214
217
|
- lib/stretchy/filters/query_filter.rb
|
215
218
|
- lib/stretchy/filters/range_filter.rb
|
216
219
|
- lib/stretchy/filters/terms_filter.rb
|
@@ -222,6 +225,7 @@ files:
|
|
222
225
|
- lib/stretchy/queries/match_all_query.rb
|
223
226
|
- lib/stretchy/queries/match_query.rb
|
224
227
|
- lib/stretchy/queries/more_like_this_query.rb
|
228
|
+
- lib/stretchy/queries/params_query.rb
|
225
229
|
- lib/stretchy/results.rb
|
226
230
|
- lib/stretchy/results/base.rb
|
227
231
|
- lib/stretchy/results/null_results.rb
|