search_flip 2.0.0.beta → 2.0.0.beta2

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: 823b618d9cd15618f5e44b441644f281f1b5598feb11f52db75a538df78761ba
4
- data.tar.gz: 3812f77dbcd670d76f9ae641f574035ff847c97b6c151f70f3fa663edf9619a6
3
+ metadata.gz: 61c625b2c60157b40c9508e6847e9727b1a468e03910afe317f39fd9687310bd
4
+ data.tar.gz: bdfc1613945464bb559243cf3d98fe9d29308d35ab2c6133db065bd9efa70322
5
5
  SHA512:
6
- metadata.gz: 2698a48a6c9e880a57776bd9bd39b21fdcbace96c5e1e50d12f81064dd3fb095d35c528c792d4f40951a9debde33dae4620928934e98596b3a32b2e9bb406c80
7
- data.tar.gz: c4ba2b7c24f4096c98e3458e6c289c1ea7f9519f3f29ebf87d882f4d7600839c8ee96eb3c07efb76ff1fe3b738b39a0f7d9036a3682d86bc5751c71f26acdcc2
6
+ metadata.gz: 24dbb5c4294827bd66b24d67a873adfb819eba35d74c393149afe5133f6b59339254e2d3348130035675b0e2ce40cdc223133db0ed52bd2e9ca34d87e9383992
7
+ data.tar.gz: 8066d64b3695d56fff2f4445602f7d4a86a815a536e825ed7a5287c5738193dfc2e4e8a81d6ea95c03e945cea564a7ff70be43c9fb97e3c30d96c972703ab57f
data/CHANGELOG.md CHANGED
@@ -3,15 +3,16 @@
3
3
 
4
4
  ## v2.0.0
5
5
 
6
- * **BREAKING**: Migration steps
7
- * Change `SearchFlip.version` to `SearchFlip::Connection#version`
8
- * Change `SearchFlip.msearch` to `SearchFlip::Connection#msearch`
9
- * Change `SearchFlip.aliases` to `SearchFlip::Connection#update_aliases`
10
- * Change `SearchFlip::Criteria#execute(base_url: '...')` to `SearchFlip::Criteria#execute(connection: SearchFlip::Connection.new(base_url: '...'))`
11
6
  * Added `SearchFlip::Connection`
12
- * Added `SearchFlip::Connection#update_aliases`
7
+ * [BREAKING] Changed `SearchFlip::Index.base_url` to `SearchFlip::Index.connection`
8
+ * [BREAKING] Changed `SearchFlip.version` to `SearchFlip::Connection#version`
9
+ * [BREAKING] Changed `SearchFlip.aliases` to `SearchFlip::Connection#update_aliases`
10
+ * [BREAKING] Changed `SearchFlip.msearch` to `SearchFlip::Connection#msearch`
11
+ * [BREAKING] Removed `base_url` param from `SearchFlip::Critiera#execute`
13
12
  * Added `SearchFlip::Connection#get_aliases`
13
+ * Added `SearchFlip::Connection#get_indices`
14
14
  * Added `SearchFlip::Connection#alias_exists?`
15
+ * Added `SearchFlip::Index#with_settings` and `SearchFlip::Criteria#with_settings`
15
16
 
16
17
  ## v1.1.0
17
18
 
data/README.md CHANGED
@@ -22,6 +22,10 @@ end
22
22
  CommentIndex.range(:created_at, gt: Date.today - 1.week, lt: Date.today).where(state: ["approved", "pending"])
23
23
  ```
24
24
 
25
+ ## Updating from previous SearchFlip versions
26
+
27
+ Checkout [UPDATING.md](./UPDATING.md) for detailed instructions.
28
+
25
29
  ## Comparison with other gems
26
30
 
27
31
  There are great ruby gems to work with Elasticsearch like e.g. searchkick and
@@ -250,6 +254,41 @@ CommentIndex.match_all.find_each do |record|
250
254
  end
251
255
  ```
252
256
 
257
+ ## Working with Elasticsearch Aliases
258
+
259
+ You can use and manage Elasticsearch Aliases like the following:
260
+
261
+ ```ruby
262
+ class UserIndex
263
+ include SearchFlip::Index
264
+
265
+ def self.index_name
266
+ alias_name
267
+ end
268
+
269
+ def self.alias_name
270
+ "users"
271
+ end
272
+ end
273
+ ```
274
+
275
+ Then, create an index, import the records and add the alias like:
276
+
277
+ ```ruby
278
+ new_user_index = UserIndex.with_settings(index_name: "users-#{SecureRandom.hex}")
279
+ new_user_index.create_index
280
+ new_user_index.import User.all
281
+ new_user.connection.update_aliases(actions: [
282
+ add: { index: new_user_index.index_name, alias: new_user_index.alias_name }
283
+ ])
284
+ ```
285
+
286
+ If the alias already exists, you of course have to remove it as well first
287
+ within `update_aliases`.
288
+
289
+ Please note that `with_settings(index_name: '...')` returns an anonymous, i.e.
290
+ temporary, class inherting from UserIndex and overwriting `index_name`.
291
+
253
292
  ## Advanced Usage
254
293
 
255
294
  SearchFlip supports even more advanced usages, like e.g. post filters, filtered
data/UPDATING.md ADDED
@@ -0,0 +1,113 @@
1
+
2
+ # Updating from previous SearchFlip versions
3
+
4
+ ## Update 1.x to 2.x
5
+
6
+ * [BREAKING] Changed `SearchFlip::Index.base_url` to `SearchFlip::Index.connection`
7
+
8
+ 1.x:
9
+
10
+ ```ruby
11
+ class MyIndex
12
+ include SearchFlip::Index
13
+
14
+ # ...
15
+
16
+ def self.base_url
17
+ "..."
18
+ end
19
+ end
20
+ ```
21
+
22
+ 2.x:
23
+
24
+ ```ruby
25
+ class MyIndex
26
+ include SearchFlip::Index
27
+
28
+ # ...
29
+
30
+ def self connection
31
+ @connection ||= SearchFlip::Connection.new(base_url: "...")
32
+ end
33
+ end
34
+ ```
35
+
36
+ * [BREAKING] Changed `SearchFlip.version` to `SearchFlip::Connection#version`
37
+
38
+ 1.x:
39
+
40
+ ```ruby
41
+ SearchFlip.version
42
+ ```
43
+
44
+ 2.x:
45
+
46
+ ```ruby
47
+ MyIndex.connection.version
48
+
49
+ # or
50
+
51
+ connection = SearchFlip::Connection.new(base_url: "...")
52
+ connection.version
53
+ ```
54
+
55
+ * [BREAKING] Changed `SearchFlip.aliases` to `SearchFlip::Connection#update_aliases`
56
+
57
+ 1.x:
58
+
59
+ ```ruby
60
+ SearchFlip.aliases(actions: [
61
+ # ...
62
+ ])
63
+ ```
64
+
65
+ 2.x:
66
+
67
+ ```ruby
68
+ MyIndex.connection.update_aliases(actions: [
69
+ # ...
70
+ ])
71
+
72
+ # or
73
+
74
+ connection = SearchFlip::Connection.new(base_url: "...")
75
+ connection.update_aliases(actions: [
76
+ # ...
77
+ ])
78
+ ```
79
+
80
+ * [BREAKING] Changed `SearchFlip.msearch` to `SearchFlip::Connection#msearch`
81
+
82
+ 1.x:
83
+
84
+ ```ruby
85
+ SearchFlip.msearch(queries)
86
+ ```
87
+
88
+ 2.x:
89
+
90
+ ```ruby
91
+ MyIndex.connection.msearch(queries)
92
+
93
+ # or
94
+
95
+ connection = SearchFlip::Connection.new(base_url: "...")
96
+ connection.msearch(queries)
97
+ ```
98
+
99
+ * [BREAKING] Removed `base_url` param from `SearchFlip::Critiera#execute`
100
+
101
+ 1.x:
102
+
103
+ ```ruby
104
+ MyIndex.where(id: 1).execute(base_url: "...")
105
+ ```
106
+
107
+ 2.x:
108
+
109
+ ```ruby
110
+ connection = SearchFlip::Connection.new(base_url: "...")
111
+ MyIndex.where(id: 1).with_settings(connection: connection).execute
112
+ ```
113
+
@@ -126,6 +126,131 @@ module SearchFlip
126
126
  .get("#{base_url}/_cat/indices/#{name}")
127
127
  .parse
128
128
  end
129
+
130
+ # Creates the specified index within ElasticSearch and applies index
131
+ # settings, if specified. Raises SearchFlip::ResponseError in case any
132
+ # errors occur.
133
+ #
134
+ # @param index_name [String] The index name
135
+ # @param index_settings [Hash] The index settings
136
+ # @return [Boolean] Returns true or raises SearchFlip::ResponseError
137
+
138
+ def create_index(index_name, index_settings = {})
139
+ SearchFlip::HTTPClient.put(index_url(index_name), json: index_settings)
140
+
141
+ true
142
+ end
143
+
144
+ # Updates the index settings within ElasticSearch according to the index
145
+ # settings specified. Raises SearchFlip::ResponseError in case any
146
+ # errors occur.
147
+ #
148
+ # @param index_name [String] The index name to update the settings for
149
+ # @param index_settings [Hash] The index settings
150
+ # @return [Boolean] Returns true or raises SearchFlip::ResponseError
151
+
152
+ def update_index_settings(index_name, index_settings)
153
+ SearchFlip::HTTPClient.put("#{index_url(index_name)}/_settings", json: index_settings)
154
+
155
+ true
156
+ end
157
+
158
+ # Fetches the index settings for the specified index from ElasticSearch.
159
+ # Sends a GET request to index_url/_settings. Raises
160
+ # SearchFlip::ResponseError in case any errors occur.
161
+ #
162
+ # @param index_name [String] The index name
163
+ # @return [Hash] The index settings
164
+
165
+ def get_index_settings(index_name)
166
+ SearchFlip::HTTPClient.headers(accept: "application/json").get("#{index_url(index_name)}/_settings").parse
167
+ end
168
+
169
+ # Sends a refresh request to ElasticSearch. Raises
170
+ # SearchFlip::ResponseError in case any errors occur.
171
+ #
172
+ # @param index_names [String, Array] The optional index names to refresh
173
+ # @return [Boolean] Returns true or raises SearchFlip::ResponseError
174
+
175
+ def refresh(index_names = nil)
176
+ SearchFlip::HTTPClient.post("#{index_names ? index_url(Array(index_names).join(",")) : base_url}/_refresh", json: {})
177
+
178
+ true
179
+ end
180
+
181
+ # Updates the type mapping for the specified index and type within
182
+ # ElasticSearch according to the specified mapping. Raises
183
+ # SearchFlip::ResponseError in case any errors occur.
184
+ #
185
+ # @param index_name [String] The index name
186
+ # @param type_name [String] The type name
187
+ # @param mapping [Hash] The mapping
188
+ # @return [Boolean] Returns true or raises SearchFlip::ResponseError
189
+
190
+ def update_mapping(index_name, type_name, mapping)
191
+ SearchFlip::HTTPClient.put("#{type_url(index_name, type_name)}/_mapping", json: mapping)
192
+
193
+ true
194
+ end
195
+
196
+ # Retrieves the mapping for the specified index and type from
197
+ # ElasticSearch. Raises SearchFlip::ResponseError in case any errors occur.
198
+ #
199
+ # @param index_name [String] The index name
200
+ # @param type_name [String] The type name
201
+ # @return [Hash] The current type mapping
202
+
203
+ def get_mapping(index_name, type_name)
204
+ SearchFlip::HTTPClient.headers(accept: "application/json").get("#{type_url(index_name, type_name)}/_mapping").parse
205
+ end
206
+
207
+ # Deletes the specified index from ElasticSearch. Raises
208
+ # SearchFlip::ResponseError in case any errors occur.
209
+ #
210
+ # @param index_name [String] The index name
211
+ # @return [Boolean] Returns true or raises SearchFlip::ResponseError
212
+
213
+ def delete_index(index_name)
214
+ SearchFlip::HTTPClient.delete index_url(index_name)
215
+
216
+ true
217
+ end
218
+
219
+ # Returns whether or not the specified index already exists.
220
+ #
221
+ # @param index_name [String] The index name
222
+ # @return [Boolean] Whether or not the index exists
223
+
224
+ def index_exists?(index_name)
225
+ SearchFlip::HTTPClient.headers(accept: "application/json").head(index_url(index_name))
226
+
227
+ true
228
+ rescue SearchFlip::ResponseError => e
229
+ return false if e.code == 404
230
+
231
+ raise e
232
+ end
233
+
234
+ # Returns the full ElasticSearch type URL, ie base URL, index name with
235
+ # prefix and type name.
236
+ #
237
+ # @param index_name [String] The index name
238
+ # @param type_name [String] The type name
239
+ # @return [String] The ElasticSearch type URL
240
+
241
+ def type_url(index_name, type_name)
242
+ "#{index_url(index_name)}/#{type_name}"
243
+ end
244
+
245
+ # Returns the ElasticSearch index URL for the specified index name, ie base
246
+ # URL and index name with prefix.
247
+ #
248
+ # @param index_name [String] The index name
249
+ # @return [String] The ElasticSearch index URL
250
+
251
+ def index_url(index_name)
252
+ "#{base_url}/#{index_name}"
253
+ end
129
254
  end
130
255
  end
131
256
 
@@ -60,7 +60,7 @@ module SearchFlip
60
60
  criteria.post_must_values = (criteria.post_must_values || []) + other.post_must_values if other.post_must_values
61
61
  criteria.post_must_not_values = (criteria.post_must_not_values || []) + other.post_must_not_values if other.post_must_not_values
62
62
  criteria.post_should_values = (criteria.post_should_values || []) + other.post_should_values if other.post_should_values
63
- criteria.post_filter_values = (criteria.post_filter_vales || []) + other.post_filter_values if other.post_filter_values
63
+ criteria.post_filter_values = (criteria.post_filter_values || []) + other.post_filter_values if other.post_filter_values
64
64
  criteria.aggregation_values = (criteria.aggregation_values || {}).merge(other.aggregation_values) if other.aggregation_values
65
65
  criteria.terminate_after_value = other.terminate_after_value unless other.terminate_after_value.nil?
66
66
  criteria.timeout_value = other.timeout_value unless other.timeout_value.nil?
@@ -149,6 +149,22 @@ module SearchFlip
149
149
  end
150
150
  end
151
151
 
152
+ # Allows to set query specific settings like e.g. connection and index
153
+ # name. Please note, however, that this should only be used for special
154
+ # cases and the subsequent query can not be serialized. Checkout
155
+ # SearchFlip::Index.with_settings for more details.
156
+ #
157
+ # @example
158
+ # UserIndex.where("...").with_settings(connection: ProxyConnection)
159
+ #
160
+ # @return [SearchFlip::Criteria] Simply returns self
161
+
162
+ def with_settings(*args)
163
+ fresh.tap do |criteria|
164
+ criteria.target = target.with_settings(*args)
165
+ end
166
+ end
167
+
152
168
  # Generates the request object from the attributes specified via chaining,
153
169
  # like eg offset, limit, query, filters, aggregations, etc and returns a
154
170
  # Hash that later gets serialized as JSON.
@@ -662,15 +678,12 @@ module SearchFlip
662
678
  # response errors will be rescued if you specify the criteria to be
663
679
  # #failsafe, such that an empty response is returned instead.
664
680
  #
665
- # @param connection An optional alternative connection to used to send the
666
- # request to for e.g. proxying
667
- #
668
681
  # @example
669
682
  # response = CommentIndex.search("hello world").execute
670
683
  #
671
684
  # @return [SearchFlip::Response] The response object
672
685
 
673
- def execute(connection: target.connection)
686
+ def execute
674
687
  @response ||= begin
675
688
  http_request = SearchFlip::HTTPClient.headers(accept: "application/json")
676
689
 
@@ -678,22 +691,22 @@ module SearchFlip
678
691
  if scroll_args && scroll_args[:id]
679
692
  if target.connection.version.to_i >= 2
680
693
  http_request.post(
681
- "#{connection.base_url}/_search/scroll",
694
+ "#{target.connection.base_url}/_search/scroll",
682
695
  json: { scroll: scroll_args[:timeout], scroll_id: scroll_args[:id] }
683
696
  )
684
697
  else
685
698
  http_request
686
699
  .headers(content_type: "text/plain")
687
- .post("#{connection.base_url}/_search/scroll", params: { scroll: scroll_args[:timeout] }, body: scroll_args[:id])
700
+ .post("#{target.connection.base_url}/_search/scroll", params: { scroll: scroll_args[:timeout] }, body: scroll_args[:id])
688
701
  end
689
702
  elsif scroll_args
690
703
  http_request.post(
691
- "#{target.type_url(connection: connection)}/_search",
704
+ "#{target.type_url}/_search",
692
705
  params: { scroll: scroll_args[:timeout] },
693
706
  json: request
694
707
  )
695
708
  else
696
- http_request.post("#{target.type_url(connection: connection)}/_search", json: request)
709
+ http_request.post("#{target.type_url}/_search", json: request)
697
710
  end
698
711
 
699
712
  SearchFlip::Response.new(self, http_response.parse)
@@ -68,6 +68,34 @@ module SearchFlip
68
68
  {}
69
69
  end
70
70
 
71
+ # Creates an anonymous class inheriting from the current index with a
72
+ # custom index name and/or connection. This is e.g. useful when working
73
+ # with aliases or proxies.
74
+ #
75
+ # @example Basic usage
76
+ # UserIndex.with_settings(index_name: 'new_user_index')
77
+ # # => #<Class:0x...>
78
+ #
79
+ # @example Working with aliases
80
+ # new_index = UserIndex.with_settings(index_name: 'new_user_index')
81
+ # new_index.create_index
82
+ # new_index.import User.all
83
+ # new_index.connection.update_aliases("...")
84
+ #
85
+ # @example Working with proxies
86
+ # query = UserIndex.with_settings(connection: ProxyConnection).where("...")
87
+ #
88
+ # @param index_name [String] A custom index_name
89
+ # @param connection [SearchFlip::Connection] A custom connection
90
+ # @return [Class] An anonymous class
91
+
92
+ def with_settings(index_name: nil, connection: nil)
93
+ Class.new(self).tap do |klass|
94
+ klass.define_singleton_method(:index_name) { index_name } if index_name
95
+ klass.define_singleton_method(:connection) { connection } if connection
96
+ end
97
+ end
98
+
71
99
  # @abstract
72
100
  #
73
101
  # Override this method to generate a hash representation of a record,
@@ -278,13 +306,7 @@ module SearchFlip
278
306
  # @return [Boolean] Whether or not the index exists
279
307
 
280
308
  def index_exists?
281
- SearchFlip::HTTPClient.headers(accept: "application/json").head(index_url)
282
-
283
- true
284
- rescue SearchFlip::ResponseError => e
285
- return false if e.code == 404
286
-
287
- raise e
309
+ connection.index_exists?(index_name_with_prefix)
288
310
  end
289
311
 
290
312
  # Fetches the index settings from ElasticSearch. Sends a GET request to
@@ -294,36 +316,38 @@ module SearchFlip
294
316
  # @return [Hash] The index settings
295
317
 
296
318
  def get_index_settings
297
- SearchFlip::HTTPClient.headers(accept: "application/json").get("#{index_url}/_settings").parse
319
+ connection.get_index_settings(index_name_with_prefix)
298
320
  end
299
321
 
300
322
  # Creates the index within ElasticSearch and applies index settings, if
301
323
  # specified. Raises SearchFlip::ResponseError in case any errors
302
324
  # occur.
325
+ #
326
+ # @param include_mapping [Boolean] Whether or not to include the mapping
327
+ # @return [Boolean] Returns true or false
303
328
 
304
- def create_index
305
- SearchFlip::HTTPClient.put(index_url, json: index_settings)
329
+ def create_index(include_mapping: false)
330
+ json = index_settings
331
+ json = json.merge(mappings: mapping) if include_mapping
306
332
 
307
- true
333
+ connection.create_index(index_name_with_prefix, json)
308
334
  end
309
335
 
310
336
  # Updates the index settings within ElasticSearch according to the index
311
337
  # settings specified. Raises SearchFlip::ResponseError in case any
312
338
  # errors occur.
339
+ #
340
+ # @return [Boolean] Returns true or false
313
341
 
314
342
  def update_index_settings
315
- SearchFlip::HTTPClient.put("#{index_url}/_settings", json: index_settings)
316
-
317
- true
343
+ connection.update_index_settings(index_name_with_prefix, index_settings)
318
344
  end
319
345
 
320
346
  # Deletes the index from ElasticSearch. Raises SearchFlip::ResponseError
321
347
  # in case any errors occur.
322
348
 
323
349
  def delete_index
324
- SearchFlip::HTTPClient.delete(index_url)
325
-
326
- true
350
+ connection.delete_index(index_name_with_prefix)
327
351
  end
328
352
 
329
353
  # Specifies a type mapping. Override to specify a custom mapping.
@@ -351,9 +375,7 @@ module SearchFlip
351
375
  # errors occur.
352
376
 
353
377
  def update_mapping
354
- SearchFlip::HTTPClient.put("#{type_url}/_mapping", json: mapping)
355
-
356
- true
378
+ connection.update_mapping(index_name_with_prefix, type_name, mapping)
357
379
  end
358
380
 
359
381
  # Retrieves the current type mapping from ElasticSearch. Raises
@@ -362,13 +384,15 @@ module SearchFlip
362
384
  # @return [Hash] The current type mapping
363
385
 
364
386
  def get_mapping
365
- SearchFlip::HTTPClient.headers(accept: "application/json").get("#{type_url}/_mapping").parse
387
+ connection.get_mapping(index_name_with_prefix, type_name)
366
388
  end
367
389
 
368
390
  # Retrieves the document specified by id from ElasticSearch. Raises
369
391
  # SearchFlip::ResponseError specific exceptions in case any errors
370
392
  # occur.
371
393
  #
394
+ # @param id [String, Fixnum] The id to get
395
+ # @param params [Hash] Optional params for the request
372
396
  # @return [Hash] The specified document
373
397
 
374
398
  def get(id, params = {})
@@ -379,9 +403,7 @@ module SearchFlip
379
403
  # SearchFlip::ResponseError in case any errors occur.
380
404
 
381
405
  def refresh
382
- SearchFlip::HTTPClient.post("#{index_url}/_refresh", json: {})
383
-
384
- true
406
+ connection.refresh(index_name_with_prefix)
385
407
  end
386
408
 
387
409
  # Indexes the given record set, array of records or individual record.
@@ -520,23 +542,19 @@ module SearchFlip
520
542
  # Returns the full ElasticSearch type URL, ie base URL, index name with
521
543
  # prefix and type name.
522
544
  #
523
- # @param connection [SearchFlip::Connection] The connection to use
524
- #
525
545
  # @return [String] The ElasticSearch type URL
526
546
 
527
- def type_url(connection: self.connection)
528
- "#{index_url(connection: connection)}/#{type_name}"
547
+ def type_url
548
+ connection.type_url(index_name_with_prefix, type_name)
529
549
  end
530
550
 
531
551
  # Returns the ElasticSearch index URL, ie base URL and index name with
532
552
  # prefix.
533
553
  #
534
- # @param connection [SearchFlip::Connection] The connection to use
535
- #
536
554
  # @return [String] The ElasticSearch index URL
537
555
 
538
- def index_url(connection: self.connection)
539
- "#{connection.base_url}/#{index_name_with_prefix}"
556
+ def index_url
557
+ connection.index_url(index_name_with_prefix)
540
558
  end
541
559
 
542
560
  # Returns the SearchFlip::Connection for the index.
@@ -1,5 +1,5 @@
1
1
 
2
2
  module SearchFlip
3
- VERSION = "2.0.0.beta"
3
+ VERSION = "2.0.0.beta2"
4
4
  end
5
5
 
@@ -66,5 +66,96 @@ class SearchFlip::ConnectionTest < SearchFlip::TestCase
66
66
  assert_equal connection.get_indices.map { |index| index["index"] }.sort, ["comments", "products"]
67
67
  assert_equal connection.get_indices("com*").map { |index| index["index"] }.sort, ["comments"]
68
68
  end
69
+
70
+ def test_create_index
71
+ connection = SearchFlip::Connection.new
72
+
73
+ assert connection.create_index("index_name")
74
+ assert connection.index_exists?("index_name")
75
+ ensure
76
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
77
+ end
78
+
79
+ def test_create_index_with_index_payload
80
+ connection = SearchFlip::Connection.new
81
+
82
+ connection.create_index("index_name", settings: { number_of_shards: 3 })
83
+
84
+ assert_equal connection.get_index_settings("index_name")["index_name"]["settings"]["index"]["number_of_shards"], "3"
85
+ ensure
86
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
87
+ end
88
+
89
+ def test_update_index_settings
90
+ connection = SearchFlip::Connection.new
91
+
92
+ connection.create_index("index_name")
93
+ connection.update_index_settings("index_name", settings: { number_of_replicas: 3 })
94
+
95
+ assert_equal "3", connection.get_index_settings("index_name")["index_name"]["settings"]["index"]["number_of_replicas"]
96
+ ensure
97
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
98
+ end
99
+
100
+ def test_get_index_settings
101
+ connection = SearchFlip::Connection.new
102
+
103
+ connection.create_index("index_name", settings: { number_of_shards: 3 })
104
+
105
+ assert_equal connection.get_index_settings("index_name")["index_name"]["settings"]["index"]["number_of_shards"], "3"
106
+ ensure
107
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
108
+ end
109
+
110
+ def test_update_mapping
111
+ connection = SearchFlip::Connection.new
112
+
113
+ mapping = { "type_name" => { "properties" => { "id" => { "type" => "long" } } } }
114
+
115
+ connection.create_index("index_name")
116
+ connection.update_mapping("index_name", "type_name", mapping)
117
+
118
+ assert_equal connection.get_mapping("index_name", "type_name"), "index_name" => { "mappings" => mapping }
119
+ ensure
120
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
121
+ end
122
+
123
+ def test_delete_index
124
+ connection = SearchFlip::Connection.new
125
+
126
+ connection.create_index("index_name")
127
+ assert connection.index_exists?("index_name")
128
+
129
+ connection.delete_index("index_name")
130
+ refute connection.index_exists?("index_name")
131
+ ensure
132
+ connection.delete_index("index_name") if connection.index_exists?("index_name")
133
+ end
134
+
135
+ def test_refresh
136
+ connection = SearchFlip::Connection.new
137
+
138
+ connection.create_index("index1")
139
+ connection.create_index("index2")
140
+
141
+ assert connection.refresh
142
+ assert connection.refresh("index1")
143
+ assert connection.refresh(["index1", "index2"])
144
+ ensure
145
+ connection.delete_index("index1") if connection.index_exists?("index1")
146
+ connection.delete_index("index2") if connection.index_exists?("index2")
147
+ end
148
+
149
+ def test_index_url
150
+ connection = SearchFlip::Connection.new(base_url: "base_url")
151
+
152
+ assert_equal "base_url/index_name", connection.index_url("index_name")
153
+ end
154
+
155
+ def test_type_url
156
+ connection = SearchFlip::Connection.new(base_url: "base_url")
157
+
158
+ assert_equal "base_url/index_name/type_name", connection.type_url("index_name", "type_name")
159
+ end
69
160
  end
70
161
 
@@ -62,6 +62,13 @@ class SearchFlip::CriteriaTest < SearchFlip::TestCase
62
62
  refute_includes query2.records, product3
63
63
  end
64
64
 
65
+ def test_with_settings
66
+ stub_request(:post, "http://127.0.0.1:9200/new_user_index/products/_search")
67
+ .to_return(status: 200, body: "{}", headers: { content_type: "application/json" })
68
+
69
+ ProductIndex.where(id: 1).with_settings(index_name: "new_user_index").execute
70
+ end
71
+
65
72
  def test_where_with_array
66
73
  expected1 = create(:product, title: "expected1")
67
74
  expected2 = create(:product, title: "expected2")
@@ -211,15 +218,6 @@ class SearchFlip::CriteriaTest < SearchFlip::TestCase
211
218
  assert_includes records, expected2
212
219
  end
213
220
 
214
- def test_execute
215
- connection = SearchFlip::Connection.new(base_url: "http://localhost:1234")
216
-
217
- stub_request(:post, "http://localhost:1234/products/products/_search")
218
- .to_return(status: 200, body: "{}", headers: { content_type: "application/json" })
219
-
220
- assert_equal ProductIndex.match_all.execute(connection: connection).raw_response, {}
221
- end
222
-
223
221
  def test_exists
224
222
  product1 = create(:product, title: "title1", description: "description1")
225
223
  product2 = create(:product, title: "title2", description: nil)
@@ -30,97 +30,166 @@ class SearchFlip::IndexTest < SearchFlip::TestCase
30
30
  end
31
31
  end
32
32
 
33
- def test_create_index
33
+ def test_create_index_works
34
34
  assert TestIndex.create_index
35
- assert TestIndex.index_exists?
36
-
37
- TestIndex.delete_index
35
+ ensure
36
+ TestIndex.delete_index if TestIndex.index_exists?
37
+ end
38
38
 
39
- refute TestIndex.index_exists?
39
+ def test_create_index_delegates_to_connection
40
+ TestIndex.connection.expects(:create_index).with("test", {})
41
+ TestIndex.create_index
40
42
  end
41
43
 
42
- def test_create_index_with_index_settings
44
+ def test_create_index_passes_index_settings_to_connection
43
45
  TestIndex.stubs(:index_settings).returns(settings: { number_of_shards: 3 })
44
-
45
46
  assert TestIndex.create_index
46
- assert TestIndex.index_exists?
47
47
 
48
- assert_equal "3", TestIndex.get_index_settings["test"]["settings"]["index"]["number_of_shards"]
48
+ assert "3", TestIndex.get_index_settings["test"]["settings"]["index"]["number_of_replicas"]
49
49
  ensure
50
50
  TestIndex.delete_index if TestIndex.index_exists?
51
51
  end
52
52
 
53
- def test_update_index_settings
53
+ def test_create_index_passes_index_settings_delegates_to_connection
54
+ TestIndex.stubs(:index_settings).returns(settings: { number_of_shards: 3 })
55
+
56
+ TestIndex.connection.expects(:create_index).with("test", settings: { number_of_shards: 3 })
57
+ TestIndex.create_index
58
+ end
59
+
60
+ def test_create_index_passes_mapping_if_specified
61
+ TestIndex.stubs(:mapping).returns(test: { properties: { id: { type: "long" } } })
54
62
  assert TestIndex.create_index
63
+ ensure
64
+ TestIndex.delete_index if TestIndex.index_exists?
65
+ end
55
66
 
56
- TestIndex.stubs(:index_settings).returns(settings: { number_of_replicas: 3 })
67
+ def test_create_index_passes_mapping_if_specified_delegates_to_connection
68
+ TestIndex.stubs(:mapping).returns(test: { properties: { id: { type: "long" } } })
57
69
 
58
- assert TestIndex.update_index_settings
70
+ TestIndex.connection.expects(:create_index).with("test", mappings: { test: { properties: { id: { type: "long" } } } })
71
+ TestIndex.create_index(include_mapping: true)
72
+ end
59
73
 
60
- assert_equal "3", TestIndex.get_index_settings["test"]["settings"]["index"]["number_of_replicas"]
74
+ def test_update_index_settings_works
75
+ TestIndex.create_index
76
+ TestIndex.stubs(:index_settings).returns(settings: { number_of_replicas: 3 })
77
+ TestIndex.update_index_settings
61
78
  ensure
62
79
  TestIndex.delete_index if TestIndex.index_exists?
63
80
  end
64
81
 
65
- def test_get_index_settings
66
- # Already tested
82
+ def test_update_index_settings_delegates_to_connection
83
+ index_settings = { settings: { number_of_replicas: 3 } }
84
+
85
+ TestIndex.stubs(:index_settings).returns(settings: { number_of_replicas: 3 })
86
+
87
+ TestIndex.connection.expects(:update_index_settings).with("test", index_settings)
88
+ TestIndex.update_index_settings
67
89
  end
68
90
 
69
- def test_index_exists?
70
- # Already tested
91
+ def test_get_index_settings_works
92
+ TestIndex.create_index
93
+ assert TestIndex.get_index_settings
94
+ ensure
95
+ TestIndex.delete_index if TestIndex.index_exists?
71
96
  end
72
97
 
73
- def test_delete_index
74
- # Already tested
98
+ def test_get_index_settings_delegates_to_connection
99
+ TestIndex.connection.expects(:get_index_settings).with("test")
100
+ TestIndex.get_index_settings
75
101
  end
76
102
 
77
- def test_update_mapping
103
+ def test_index_exists_works
78
104
  TestIndex.create_index
79
- TestIndex.update_mapping
105
+ assert TestIndex.index_exists?
106
+ ensure
107
+ TestIndex.delete_index if TestIndex.index_exists?
108
+ end
80
109
 
81
- mapping = TestIndex.get_mapping
110
+ def test_index_exists_delegates_to_connection
111
+ TestIndex.connection.expects(:index_exists?).with("test")
112
+ TestIndex.index_exists?
113
+ end
82
114
 
83
- assert mapping["test"]["mappings"]["test"]["properties"]["test_field"]
115
+ def test_delete_index_works
116
+ TestIndex.create_index
117
+ assert TestIndex.delete_index
118
+ ensure
119
+ TestIndex.delete_index if TestIndex.index_exists?
120
+ end
84
121
 
122
+ def test_delete_index_delegates_to_connection
123
+ TestIndex.connection.expects(:delete_index).with("test")
85
124
  TestIndex.delete_index
86
125
  end
87
126
 
88
- def test_get_mapping
89
- # Aready tested
127
+ def test_update_mapping_works
128
+ TestIndex.stubs(:mapping).returns(test: { properties: { id: { type: "long" } } })
129
+
130
+ TestIndex.create_index
131
+ TestIndex.update_mapping
132
+ ensure
133
+ TestIndex.delete_index if TestIndex.index_exists?
90
134
  end
91
135
 
92
- def test_refresh
93
- assert_difference "ProductIndex.total_entries" do
94
- ProductIndex.import create(:product)
136
+ def test_update_mapping_delegates_to_connection
137
+ mapping = { test: { properties: { id: { type: "long" } } } }
95
138
 
96
- assert ProductIndex.refresh
97
- end
139
+ TestIndex.stubs(:mapping).returns(mapping)
140
+
141
+ TestIndex.connection.expects(:update_mapping).with("test", "test", mapping)
142
+ TestIndex.update_mapping
98
143
  end
99
144
 
100
- def test_index_url
101
- assert_equal "http://127.0.0.1:9200/products", ProductIndex.index_url
145
+ def test_get_mapping_works
146
+ TestIndex.create_index
147
+ TestIndex.update_mapping
102
148
 
103
- ProductIndex.stubs(:type_name).returns("products2")
149
+ assert TestIndex.get_mapping
150
+ ensure
151
+ TestIndex.delete_index if TestIndex.index_exists?
152
+ end
104
153
 
105
- assert_equal "http://127.0.0.1:9200/products2", ProductIndex.index_url
154
+ def test_get_mapping_delegates_to_connection
155
+ TestIndex.connection.expects(:get_mapping).with("test", "test")
156
+ TestIndex.get_mapping
157
+ end
106
158
 
107
- SearchFlip::Config[:index_prefix] = "prefix-"
159
+ def test_refresh_works
160
+ TestIndex.create_index
161
+ TestIndex.refresh
162
+ ensure
163
+ TestIndex.delete_index if TestIndex.index_exists?
164
+ end
108
165
 
109
- assert_equal "http://127.0.0.1:9200/prefix-products2", ProductIndex.index_url
166
+ def test_refresh_delegates_to_connection
167
+ TestIndex.connection.expects(:refresh).with("test")
168
+ TestIndex.refresh
169
+ end
110
170
 
111
- ProductIndex.stubs(:index_name).returns("products3")
171
+ def test_index_url
172
+ assert TestIndex.index_url
173
+ end
112
174
 
113
- assert_equal "http://127.0.0.1:9200/prefix-products3", ProductIndex.index_url
175
+ def test_index_url_delegates_to_connection
176
+ TestIndex.connection.expects(:index_url).with("test")
177
+ TestIndex.index_url
114
178
 
179
+ SearchFlip::Config[:index_prefix] = "prefix-"
180
+ TestIndex.connection.expects(:index_url).with("prefix-test")
181
+ TestIndex.index_url
182
+ ensure
115
183
  SearchFlip::Config[:index_prefix] = nil
116
184
  end
117
185
 
118
186
  def test_type_url
119
- assert_equal "http://127.0.0.1:9200/products/products", ProductIndex.type_url
120
-
121
- ProductIndex.stubs(:type_name).returns("products2")
187
+ assert TestIndex.type_url
188
+ end
122
189
 
123
- assert_equal "http://127.0.0.1:9200/products2/products2", ProductIndex.type_url
190
+ def test_type_url_delegates_to_connection
191
+ TestIndex.connection.expects(:type_url).with("test", "test")
192
+ TestIndex.type_url
124
193
  end
125
194
 
126
195
  def test_import_object
@@ -376,7 +445,7 @@ class SearchFlip::IndexTest < SearchFlip::TestCase
376
445
  end
377
446
 
378
447
  def test_connection
379
- assert_equal ProductIndex.connection.base_url, "http://127.0.0.1:9200"
448
+ assert_equal "http://127.0.0.1:9200", ProductIndex.connection.base_url
380
449
  end
381
450
  end
382
451
 
data/test/test_helper.rb CHANGED
@@ -238,5 +238,6 @@ class SearchFlip::TestCase < MiniTest::Test
238
238
  def setup
239
239
  ProductIndex.match_all.delete
240
240
  Product.delete_all
241
+ TestIndex.delete_index if TestIndex.index_exists?
241
242
  end
242
243
  end
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.beta
4
+ version: 2.0.0.beta2
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-02-20 00:00:00.000000000 Z
11
+ date: 2019-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -193,6 +193,7 @@ files:
193
193
  - LICENSE.txt
194
194
  - README.md
195
195
  - Rakefile
196
+ - UPDATING.md
196
197
  - docker-compose.yml
197
198
  - lib/search_flip.rb
198
199
  - lib/search_flip/aggregatable.rb