stretchy 0.4.6 → 0.4.7

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.
@@ -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
- # Options passed to the initializer will be interpreted as filters
28
- # to be added to the query. This is similar to ActiveRecord's `where`
29
- # method.
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
- # @option params [true, false] :inverted (nil) Whether the new state is inverted
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[:inverse] = true if inverse?
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[:inverse] = true if inverse?
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
@@ -8,3 +8,4 @@ require 'stretchy/filters/or_filter'
8
8
  require 'stretchy/filters/query_filter'
9
9
  require 'stretchy/filters/range_filter'
10
10
  require 'stretchy/filters/terms_filter'
11
+ require 'stretchy/filters/params_filter'
@@ -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
@@ -5,3 +5,4 @@ require 'stretchy/queries/function_score_query'
5
5
  require 'stretchy/queries/match_all_query'
6
6
  require 'stretchy/queries/match_query'
7
7
  require 'stretchy/queries/more_like_this_query'
8
+ require 'stretchy/queries/params_query'
@@ -1,3 +1,3 @@
1
1
  module Stretchy
2
- VERSION = "0.4.6"
2
+ VERSION = "0.4.7"
3
3
  end
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.6
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-26 00:00:00.000000000 Z
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