search_flip 2.0.0.beta3 → 2.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 55f88fe9b429304c6f605a0175b3b711334cf47613facc78864511b012e2eb4e
4
- data.tar.gz: 12c5e164eb18caaf72a361c7d1ba24f9b0324c412f2c7712f79f87e9248dbf1c
3
+ metadata.gz: c626b4c449c70b071fee204d164b226271d2f098ae48f4c54568e07b6ad8d9d8
4
+ data.tar.gz: f35599e1cd57a27fe3c008fa20538be08fa9f7251a5c421d25fd98113d2a6cc7
5
5
  SHA512:
6
- metadata.gz: 26842b8df4ee2014ee77f1429ab6438350f45458e150fe1786f654bb2d925c53524007d2ec88bed42f80d0983887b8720c19b617ec1e00de8de8964c70a602dd
7
- data.tar.gz: 6976b12cd544bbc19f88fb69e855c6107badd49c565578b6b5a75b07d63d85ad4d85762e0e18b02010b9376123f44c8bb73dc81676e3f28cdd5b9ab9d237659c
6
+ metadata.gz: 95df5e882633308f0dcbcac35d155901db7bfee39f0f37d1ee84c055fdde821a22b697fd0df5ea4ab82204896c3adb483769cae85b1489ec2eca28c4fc0e2de5
7
+ data.tar.gz: e97fceeacf0186b99829fb70d9a8eb396455c2f2cf3dec58e2f357dd5b8bd542025e7ee33201757af02c45b90752da70e6d28e6cbff2605fc36d0fd7ac9638d2
data/UPDATING.md CHANGED
@@ -127,3 +127,48 @@ query = CommentIndex.highlight(:title).search("hello")
127
127
  query.results[0]._hit.highlight.title # => "<em>hello</em> world"
128
128
  ```
129
129
 
130
+ * **[BREAKING]** `index_name` no longer defaults to `type_name`
131
+
132
+ 1.x:
133
+
134
+ ```ruby
135
+ class CommentIndex
136
+ include SearchFlip::Index
137
+
138
+ def self.type_name
139
+ "comments"
140
+ end
141
+
142
+ # CommentIndex.index_name defaults to CommentIndex.type_name
143
+ end
144
+ ```
145
+
146
+ 2.x:
147
+
148
+ ```ruby
149
+ class CommentIndex
150
+ include SearchFlip::Index
151
+
152
+ def self.type_name
153
+ "comments"
154
+ end
155
+
156
+ def self.index_name
157
+ "comments"
158
+ end
159
+ end
160
+ ```
161
+
162
+ * **[BREAKING]** Multiple calls to `source` no longer concatenate
163
+
164
+ 1.x:
165
+
166
+ ```ruby
167
+ CommentIndex.source([:id]).source([:description]) # => CommentIndex.source([:id, :description])
168
+ ```
169
+
170
+ 2.x:
171
+
172
+ ```ruby
173
+ CommentIndex.source([:id]).source([:description]) # => CommentIndex.source([:description])
174
+ ```
@@ -49,6 +49,53 @@ module SearchFlip
49
49
  res
50
50
  end
51
51
 
52
+ # @api private
53
+ #
54
+ # Merges a criteria into the aggregation.
55
+ #
56
+ # @param other [SearchFlip::Criteria] The criteria to merge in
57
+ #
58
+ # @return [SearchFlip::Aggregation] A fresh aggregation including the merged criteria
59
+
60
+ def merge(other)
61
+ other = other.criteria
62
+
63
+ fresh.tap do |aggregation|
64
+ unsupported_methods = [
65
+ :profile_value, :failsafe_value, :terminate_after_value, :timeout_value, :offset_value, :limit_value,
66
+ :scroll_args, :highlight_values, :suggest_values, :custom_value, :source_value, :sort_values,
67
+ :includes_values, :preload_values, :eager_load_values, :post_search_values, :post_must_values,
68
+ :post_must_not_values, :post_should_values, :post_filter_values
69
+ ]
70
+
71
+ unsupported_methods.each do |unsupported_method|
72
+ unless other.send(unsupported_method).nil?
73
+ raise(SearchFlip::NotSupportedError, "Using #{unsupported_method} within aggregations is not supported")
74
+ end
75
+ end
76
+
77
+ aggregation.search_values = (aggregation.search_values || []) + other.search_values if other.search_values
78
+ aggregation.must_values = (aggregation.must_values || []) + other.must_values if other.must_values
79
+ aggregation.must_not_values = (aggregation.must_not_values || []) + other.must_not_values if other.must_not_values
80
+ aggregation.should_values = (aggregation.should_values || []) + other.should_values if other.should_values
81
+ aggregation.filter_values = (aggregation.filter_values || []) + other.filter_values if other.filter_values
82
+
83
+ aggregation.aggregation_values = (aggregation.aggregation_values || {}).merge(other.aggregation_values) if other.aggregation_values
84
+ end
85
+ end
86
+
87
+ def respond_to_missing?(name, *args)
88
+ target.respond_to?(name, *args)
89
+ end
90
+
91
+ def method_missing(name, *args, &block)
92
+ if target.respond_to?(name)
93
+ merge(target.send(name, *args, &block))
94
+ else
95
+ super
96
+ end
97
+ end
98
+
52
99
  # @api private
53
100
  #
54
101
  # Simply dups the object for api compatability.
@@ -137,12 +137,15 @@ module SearchFlip
137
137
  .parse
138
138
  end
139
139
 
140
+ alias_method :cat_indices, :get_indices
141
+
140
142
  # Creates the specified index within ElasticSearch and applies index
141
143
  # settings, if specified. Raises SearchFlip::ResponseError in case any
142
144
  # errors occur.
143
145
  #
144
146
  # @param index_name [String] The index name
145
147
  # @param index_settings [Hash] The index settings
148
+ #
146
149
  # @return [Boolean] Returns true or raises SearchFlip::ResponseError
147
150
 
148
151
  def create_index(index_name, index_settings = {})
@@ -157,6 +160,7 @@ module SearchFlip
157
160
  #
158
161
  # @param index_name [String] The index name to update the settings for
159
162
  # @param index_settings [Hash] The index settings
163
+ #
160
164
  # @return [Boolean] Returns true or raises SearchFlip::ResponseError
161
165
 
162
166
  def update_index_settings(index_name, index_settings)
@@ -170,6 +174,7 @@ module SearchFlip
170
174
  # SearchFlip::ResponseError in case any errors occur.
171
175
  #
172
176
  # @param index_name [String] The index name
177
+ #
173
178
  # @return [Hash] The index settings
174
179
 
175
180
  def get_index_settings(index_name)
@@ -195,6 +200,7 @@ module SearchFlip
195
200
  # @param index_name [String] The index name
196
201
  # @param type_name [String] The type name
197
202
  # @param mapping [Hash] The mapping
203
+ #
198
204
  # @return [Boolean] Returns true or raises SearchFlip::ResponseError
199
205
 
200
206
  def update_mapping(index_name, type_name, mapping)
@@ -208,6 +214,7 @@ module SearchFlip
208
214
  #
209
215
  # @param index_name [String] The index name
210
216
  # @param type_name [String] The type name
217
+ #
211
218
  # @return [Hash] The current type mapping
212
219
 
213
220
  def get_mapping(index_name, type_name)
@@ -218,6 +225,7 @@ module SearchFlip
218
225
  # SearchFlip::ResponseError in case any errors occur.
219
226
  #
220
227
  # @param index_name [String] The index name
228
+ #
221
229
  # @return [Boolean] Returns true or raises SearchFlip::ResponseError
222
230
 
223
231
  def delete_index(index_name)
@@ -229,6 +237,7 @@ module SearchFlip
229
237
  # Returns whether or not the specified index already exists.
230
238
  #
231
239
  # @param index_name [String] The index name
240
+ #
232
241
  # @return [Boolean] Whether or not the index exists
233
242
 
234
243
  def index_exists?(index_name)
@@ -246,6 +255,7 @@ module SearchFlip
246
255
  #
247
256
  # @param index_name [String] The index name
248
257
  # @param type_name [String] The type name
258
+ #
249
259
  # @return [String] The ElasticSearch type URL
250
260
 
251
261
  def type_url(index_name, type_name)
@@ -256,6 +266,7 @@ module SearchFlip
256
266
  # URL and index name with prefix.
257
267
  #
258
268
  # @param index_name [String] The index name
269
+ #
259
270
  # @return [String] The ElasticSearch index URL
260
271
 
261
272
  def index_url(index_name)
@@ -45,8 +45,8 @@ module SearchFlip
45
45
  criteria.offset_value = other.offset_value if other.offset_value
46
46
  criteria.limit_value = other.limit_value if other.limit_value
47
47
  criteria.scroll_args = other.scroll_args if other.scroll_args
48
+ criteria.source_value = other.source_value if other.source_value
48
49
 
49
- criteria.source_value = (criteria.source_value || []) + other.source_value if other.source_value
50
50
  criteria.sort_values = (criteria.sort_values || []) + other.sort_values if other.sort_values
51
51
  criteria.includes_values = (criteria.includes_values || []) + other.includes_values if other.includes_values
52
52
  criteria.preload_values = (criteria.preload_values || []) + other.preload_values if other.preload_values
@@ -122,7 +122,7 @@ module SearchFlip
122
122
 
123
123
  fresh.tap do |criteria|
124
124
  criteria.search_values = nil if scopes.include?(:search)
125
- criteria.post_search_values = nil if scopes.include?(:search)
125
+ criteria.post_search_values = nil if scopes.include?(:post_search)
126
126
  criteria.sort_values = nil if scopes.include?(:sort)
127
127
  criteria.hightlight_values = nil if scopes.include?(:highlight)
128
128
  criteria.suggest_values = nil if scopes.include?(:suggest)
@@ -375,8 +375,10 @@ module SearchFlip
375
375
  #
376
376
  # @example
377
377
  # CommentIndex.source([:id, :message]).search("hello world")
378
+ # CommentIndex.source(exclude: "description")
379
+ # CommentIndex.source(false)
378
380
  #
379
- # @param value [Array] Array listing the field names of the source document
381
+ # @param value Pass any allowed value to restrict the returned source
380
382
  #
381
383
  # @return [SearchFlip::Criteria] A newly created extended criteria
382
384
 
@@ -87,6 +87,7 @@ module SearchFlip
87
87
  #
88
88
  # @param index_name [String] A custom index_name
89
89
  # @param connection [SearchFlip::Connection] A custom connection
90
+ #
90
91
  # @return [Class] An anonymous class
91
92
 
92
93
  def with_settings(index_name: nil, connection: nil)
@@ -113,6 +114,7 @@ module SearchFlip
113
114
  # end
114
115
  #
115
116
  # @param record The record that gets serialized
117
+ #
116
118
  # @return [Hash] The hash-representation of the record
117
119
 
118
120
  def serialize(record)
@@ -178,6 +180,7 @@ module SearchFlip
178
180
  # end
179
181
  #
180
182
  # @param record The record to get the primary key for
183
+ #
181
184
  # @return [String, Fixnum] The record's primary key
182
185
 
183
186
  def record_id(record)
@@ -189,6 +192,7 @@ module SearchFlip
189
192
  # keys and/or ORMs.
190
193
  #
191
194
  # @param ids [Array] The array of ids to fetch the records for
195
+ #
192
196
  # @return The record set or an array of records
193
197
 
194
198
  def fetch_records(ids)
@@ -267,7 +271,7 @@ module SearchFlip
267
271
  # @return [String] The base name of the index, ie without prefix
268
272
 
269
273
  def index_name
270
- type_name
274
+ raise SearchFlip::MethodNotImplemented, "You must implement #{name}::index_name"
271
275
  end
272
276
 
273
277
  # @api private
@@ -324,6 +328,7 @@ module SearchFlip
324
328
  # occur.
325
329
  #
326
330
  # @param include_mapping [Boolean] Whether or not to include the mapping
331
+ #
327
332
  # @return [Boolean] Returns true or false
328
333
 
329
334
  def create_index(include_mapping: false)
@@ -393,6 +398,7 @@ module SearchFlip
393
398
  #
394
399
  # @param id [String, Fixnum] The id to get
395
400
  # @param params [Hash] Optional params for the request
401
+ #
396
402
  # @return [Hash] The specified document
397
403
 
398
404
  def get(id, params = {})
@@ -1,5 +1,5 @@
1
1
 
2
2
  module SearchFlip
3
- VERSION = "2.0.0.beta3"
3
+ VERSION = "2.0.0.beta4"
4
4
  end
5
5
 
@@ -262,4 +262,122 @@ RSpec.describe SearchFlip::Aggregation do
262
262
  expect(query.aggregations(:category)["category2"].title.buckets.detect { |bucket| bucket[:key] == "title2" }.price.value).to eq(60)
263
263
  end
264
264
  end
265
+
266
+ describe "#merge" do
267
+ it "merges a criteria into the aggregation" do
268
+ product1 = create(:product, price: 100, category: "category1")
269
+ product2 = create(:product, price: 150, category: "category1")
270
+ product3 = create(:product, price: 200, category: "category2")
271
+ product4 = create(:product, price: 300, category: "category1")
272
+
273
+ ProductIndex.import [product1, product2, product3, product4]
274
+
275
+ query = ProductIndex.aggregate(categories: {}) do |agg|
276
+ agg.merge(ProductIndex.where(price: 100..200)).aggregate(:category)
277
+ end
278
+
279
+ result = query.aggregations(:categories).category.buckets.each_with_object({}) do |bucket, hash|
280
+ hash[bucket["key"]] = bucket.doc_count
281
+ end
282
+
283
+ expect(result).to eq("category1" => 2, "category2" => 1)
284
+ end
285
+
286
+ describe "unsupported methods" do
287
+ unsupported_methods = [
288
+ :profile_value, :failsafe_value, :terminate_after_value, :timeout_value, :offset_value, :limit_value,
289
+ :scroll_args, :highlight_values, :suggest_values, :custom_value, :source_value, :sort_values,
290
+ :includes_values, :preload_values, :eager_load_values, :post_search_values, :post_must_values,
291
+ :post_must_not_values, :post_should_values, :post_filter_values
292
+ ]
293
+
294
+ unsupported_methods.each do |unsupported_method|
295
+ it "raises a NotSupportedError #{unsupported_method}" do
296
+ block = lambda do
297
+ TestIndex.aggregate(field: {}) do |agg|
298
+ criteria = SearchFlip::Criteria.new(target: TestIndex)
299
+ criteria.send("#{unsupported_method}=", "value")
300
+
301
+ agg.merge(criteria)
302
+ end
303
+ end
304
+
305
+ expect(&block).to raise_error(SearchFlip::NotSupportedError)
306
+ end
307
+ end
308
+ end
309
+
310
+ describe "array concatenations" do
311
+ methods = [:search_values, :must_values, :must_not_values, :should_values, :filter_values]
312
+
313
+ methods.each do |method|
314
+ it "concatenates the values for #{method}" do
315
+ aggregation = SearchFlip::Aggregation.new(target: TestIndex)
316
+ aggregation.send("#{method}=", ["value1"])
317
+
318
+ criteria = SearchFlip::Criteria.new(target: TestIndex)
319
+ criteria.send("#{method}=", ["value2"])
320
+
321
+ result = aggregation.merge(criteria)
322
+
323
+ expect(result.send(method)).to eq(["value1", "value2"])
324
+ end
325
+ end
326
+ end
327
+
328
+ describe "hash merges" do
329
+ methods = [:aggregation_values]
330
+
331
+ methods.each do |method|
332
+ it "merges the values for #{method}" do
333
+ aggregation = SearchFlip::Aggregation.new(target: TestIndex)
334
+ aggregation.send("#{method}=", key1: "value1")
335
+
336
+ criteria = SearchFlip::Criteria.new(target: TestIndex)
337
+ criteria.send("#{method}=", key2: "value2")
338
+
339
+ result = aggregation.merge(criteria)
340
+
341
+ expect(result.send(method)).to eq(key1: "value1", key2: "value2")
342
+ end
343
+ end
344
+ end
345
+ end
346
+
347
+ describe "#respond_to?" do
348
+ it "checks whether or not the index class responds to the method" do
349
+ temp_index = Class.new(ProductIndex)
350
+ aggregation = SearchFlip::Aggregation.new(target: temp_index)
351
+
352
+ expect(aggregation.respond_to?(:test_scope)).to eq(false)
353
+
354
+ temp_index.scope(:test_scope) { match_all }
355
+
356
+ expect(aggregation.respond_to?(:test_scope)).to eq(true)
357
+ end
358
+ end
359
+
360
+ describe "#method_missing" do
361
+ it "delegates to the index class" do
362
+ temp_index = Class.new(ProductIndex)
363
+ temp_index.scope(:with_price_range) { |range| where(price: range) }
364
+
365
+ product1 = create(:product, price: 100, category: "category1")
366
+ product2 = create(:product, price: 150, category: "category1")
367
+ product3 = create(:product, price: 200, category: "category2")
368
+ product4 = create(:product, price: 300, category: "category1")
369
+
370
+ temp_index.import [product1, product2, product3, product4]
371
+
372
+ query = temp_index.aggregate(categories: {}) do |agg|
373
+ agg.merge(temp_index.with_price_range(100..200)).aggregate(:category)
374
+ end
375
+
376
+ result = query.aggregations(:categories).category.buckets.each_with_object({}) do |bucket, hash|
377
+ hash[bucket["key"]] = bucket.doc_count
378
+ end
379
+
380
+ expect(result).to eq("category1" => 2, "category2" => 1)
381
+ end
382
+ end
265
383
  end
@@ -35,7 +35,7 @@ RSpec.describe SearchFlip::Criteria do
35
35
  describe "assignments" do
36
36
  methods = [
37
37
  :profile_value, :failsafe_value, :terminate_after_value, :timeout_value,
38
- :offset_value, :limit_value, :scroll_args
38
+ :offset_value, :limit_value, :scroll_args, :source_value
39
39
  ]
40
40
 
41
41
  methods.each do |method|
@@ -53,10 +53,9 @@ RSpec.describe SearchFlip::Criteria do
53
53
 
54
54
  describe "array concatenations" do
55
55
  methods = [
56
- :source_value, :sort_values, :includes_values, :preload_values, :eager_load_values,
57
- :search_values, :must_values, :must_not_values, :should_values, :filter_values,
58
- :post_search_values, :post_must_values, :post_must_not_values, :post_should_values,
59
- :post_filter_values
56
+ :sort_values, :includes_values, :preload_values, :eager_load_values, :search_values,
57
+ :must_values, :must_not_values, :should_values, :filter_values, :post_search_values,
58
+ :post_must_values, :post_must_not_values, :post_should_values, :post_filter_values
60
59
  ]
61
60
 
62
61
  methods.each do |method|
@@ -42,6 +42,16 @@ RSpec.describe SearchFlip::Index do
42
42
  end
43
43
  end
44
44
 
45
+ describe ".type_name" do
46
+ it "raises a SearchFlip::MethodNotImplemented by default" do
47
+ klass = Class.new do
48
+ include SearchFlip::Index
49
+ end
50
+
51
+ expect { klass.index_name }.to raise_error(SearchFlip::MethodNotImplemented)
52
+ end
53
+ end
54
+
45
55
  describe ".create_index" do
46
56
  it "delegates to connection" do
47
57
  allow(TestIndex.connection).to receive(:create_index).and_call_original
data/spec/spec_helper.rb CHANGED
@@ -88,6 +88,10 @@ class CommentIndex
88
88
  "comments"
89
89
  end
90
90
 
91
+ def self.index_name
92
+ "comments"
93
+ end
94
+
91
95
  def self.model
92
96
  Comment
93
97
  end
@@ -136,6 +140,10 @@ class ProductIndex
136
140
  "products"
137
141
  end
138
142
 
143
+ def self.index_name
144
+ "products"
145
+ end
146
+
139
147
  def self.model
140
148
  Product
141
149
  end
@@ -174,6 +182,10 @@ class TestIndex
174
182
  def self.type_name
175
183
  "test"
176
184
  end
185
+
186
+ def self.index_name
187
+ "test"
188
+ end
177
189
  end
178
190
 
179
191
  TestIndex.delete_index if TestIndex.index_exists?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: search_flip
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.beta3
4
+ version: 2.0.0.beta4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Vetter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-07 00:00:00.000000000 Z
11
+ date: 2019-03-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord