stretchy 0.4.6 → 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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