search_flip 2.0.0.beta → 2.0.0.beta2

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