search_flip 2.0.0.beta3 → 2.0.0.beta4

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 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