meilisearch 0.15.4 → 0.17.1

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: 03f23776fd7b1baeabbfcc33fcd848f8bd89f56655579756d9e2c06492f8d824
4
- data.tar.gz: d5137b74a7def336e41e746d56f714847be1f73185c5f05abf70a03310cc79b4
3
+ metadata.gz: d989f446194c8260cc87880abfaaf641d0e4b88ae80300d7f9d99fd4c6edfd2e
4
+ data.tar.gz: cbec6b1faeab1d84990b7b1390eb386e536bbaa2442231593d1377b5a5ba0da4
5
5
  SHA512:
6
- metadata.gz: c2c1fee375d80f6e0c372438b3fbb4c76b4c504f0c7ddf1d12d810e89f93f8173e838b1d6d8cf1d57ba02f75277f784660379c8961ccb47884eb2e37d7a43f06
7
- data.tar.gz: ab566b980a0ab15a5ffef99fb47520f667783c098e3ea81fa35784a12d1806846b18a80f42116f0605e2770655a62f35b97e8881983b08ff865de28fcde89c7a
6
+ metadata.gz: 328b4fcec0d6ca099c34ee40340a5a191cec576cbef198a4b0a18fd0afaa1c77708146531204347e67a0037599a35b7caa514940674f28e5a8b06ecaba7ba55c
7
+ data.tar.gz: db01b2e587efc423138437505840b73879d26a0a5d340eb3f1ea56753b8e2f7eaba6f13b22e1a464c8bfec9728b1af42e0c164a735e624844a1a81a99504bd5f
@@ -6,15 +6,22 @@ module MeiliSearch
6
6
  class Client < HTTPRequest
7
7
  ### INDEXES
8
8
 
9
+ def raw_indexes
10
+ http_get('/indexes')
11
+ end
12
+
9
13
  def indexes
10
- http_get '/indexes'
14
+ raw_indexes.map do |index_hash|
15
+ index_object(index_hash['uid'], index_hash['primaryKey'])
16
+ end
11
17
  end
12
18
 
13
19
  # Usage:
14
20
  # client.create_index('indexUID')
15
21
  # client.create_index('indexUID', primaryKey: 'id')
16
22
  def create_index(index_uid, options = {})
17
- body = options.merge(uid: index_uid)
23
+ body = Utils.transform_attributes(options.merge(uid: index_uid))
24
+
18
25
  index_hash = http_post '/indexes', body
19
26
  index_object(index_hash['uid'], index_hash['primaryKey'])
20
27
  end
@@ -34,6 +41,17 @@ module MeiliSearch
34
41
  index_object(index_uid).delete
35
42
  end
36
43
 
44
+ # Usage:
45
+ # client.delete_index_if_exists('indexUID')
46
+ def delete_index_if_exists(index_uid)
47
+ index_object(index_uid).delete
48
+ true
49
+ rescue ApiError => e
50
+ raise e if e.code != 'index_not_found'
51
+
52
+ false
53
+ end
54
+
37
55
  # Usage:
38
56
  # client.index('indexUID')
39
57
  def index(index_uid)
@@ -44,6 +62,10 @@ module MeiliSearch
44
62
  index_object(index_uid).fetch_info
45
63
  end
46
64
 
65
+ def fetch_raw_index(index_uid)
66
+ index_object(index_uid).fetch_raw_info
67
+ end
68
+
47
69
  ### KEYS
48
70
 
49
71
  def keys
@@ -29,10 +29,15 @@ module MeiliSearch
29
29
 
30
30
  def get_meilisearch_error_info(http_body)
31
31
  @http_body = JSON.parse(http_body)
32
- @ms_code = @http_body['errorCode']
32
+ @ms_code = @http_body['code']
33
33
  @ms_message = @http_body['message']
34
- @ms_type = @http_body['errorType']
35
- @ms_link = @http_body['errorLink']
34
+ @ms_type = @http_body['type']
35
+ @ms_link = @http_body['link']
36
+ rescue JSON::ParserError
37
+ # We might receive a JSON::ParserError when, for example, MeiliSearch is running behind
38
+ # some proxy (ELB or Nginx, for example), and the request timeouts, returning us
39
+ # a raw HTML body instead of a JSON as we were expecting
40
+ @ms_message = "The server has not returned a valid JSON HTTP body: #{http_body}"
36
41
  end
37
42
 
38
43
  def details
@@ -17,13 +17,17 @@ module MeiliSearch
17
17
  'Content-Type' => 'application/json',
18
18
  'X-Meili-API-Key' => api_key
19
19
  }.compact
20
+ @headers_no_body = {
21
+ 'X-Meili-API-Key' => api_key
22
+ }.compact
20
23
  end
21
24
 
22
25
  def http_get(relative_path = '', query_params = {})
23
26
  send_request(
24
27
  proc { |path, config| self.class.get(path, config) },
25
28
  relative_path,
26
- query_params
29
+ query_params: query_params,
30
+ headers: @headers_no_body
27
31
  )
28
32
  end
29
33
 
@@ -31,8 +35,9 @@ module MeiliSearch
31
35
  send_request(
32
36
  proc { |path, config| self.class.post(path, config) },
33
37
  relative_path,
34
- query_params,
35
- body
38
+ query_params: query_params,
39
+ body: body,
40
+ headers: @headers
36
41
  )
37
42
  end
38
43
 
@@ -40,22 +45,24 @@ module MeiliSearch
40
45
  send_request(
41
46
  proc { |path, config| self.class.put(path, config) },
42
47
  relative_path,
43
- query_params,
44
- body
48
+ query_params: query_params,
49
+ body: body,
50
+ headers: @headers
45
51
  )
46
52
  end
47
53
 
48
54
  def http_delete(relative_path = '')
49
55
  send_request(
50
56
  proc { |path, config| self.class.delete(path, config) },
51
- relative_path
57
+ relative_path,
58
+ headers: @headers_no_body
52
59
  )
53
60
  end
54
61
 
55
62
  private
56
63
 
57
- def send_request(http_method, relative_path, query_params = nil, body = nil)
58
- config = http_config(query_params, body)
64
+ def send_request(http_method, relative_path, query_params: nil, body: nil, headers: nil)
65
+ config = http_config(query_params, body, headers)
59
66
  begin
60
67
  response = http_method.call(@base_url + relative_path, config)
61
68
  rescue Errno::ECONNREFUSED => e
@@ -64,12 +71,11 @@ module MeiliSearch
64
71
  validate(response)
65
72
  end
66
73
 
67
- def http_config(query_params, body)
68
- body = body.to_json
74
+ def http_config(query_params, body, headers)
69
75
  {
70
- headers: @headers,
76
+ headers: headers,
71
77
  query: query_params,
72
- body: body,
78
+ body: body.to_json,
73
79
  timeout: @options[:timeout] || 1,
74
80
  max_retries: @options[:max_retries] || 0
75
81
  }.compact
@@ -5,7 +5,7 @@ require 'timeout'
5
5
 
6
6
  module MeiliSearch
7
7
  class Index < HTTPRequest
8
- attr_reader :uid, :primary_key
8
+ attr_reader :uid, :primary_key, :created_at, :updated_at
9
9
 
10
10
  def initialize(index_uid, url, api_key = nil, primary_key = nil, options = {})
11
11
  @uid = index_uid
@@ -14,27 +14,47 @@ module MeiliSearch
14
14
  end
15
15
 
16
16
  def fetch_info
17
- index_hash = http_get "/indexes/#{@uid}"
18
- @primary_key = index_hash['primaryKey']
17
+ index_hash = http_get indexes_path(id: @uid)
18
+ set_base_properties index_hash
19
19
  self
20
20
  end
21
21
 
22
+ def fetch_primary_key
23
+ fetch_info.primary_key
24
+ end
25
+ alias get_primary_key fetch_primary_key
26
+
27
+ def fetch_raw_info
28
+ index_hash = http_get indexes_path(id: @uid)
29
+ set_base_properties index_hash
30
+ index_hash
31
+ end
32
+
22
33
  def update(body)
23
- index_hash = http_put "/indexes/#{@uid}", body
24
- @primary_key = index_hash['primaryKey']
34
+ index_hash = http_put indexes_path(id: @uid), Utils.transform_attributes(body)
35
+ set_base_properties index_hash
36
+
25
37
  self
26
38
  end
39
+
27
40
  alias update_index update
28
41
 
29
42
  def delete
30
- http_delete "/indexes/#{@uid}"
43
+ http_delete indexes_path(id: @uid)
31
44
  end
32
45
  alias delete_index delete
33
46
 
34
- def fetch_primary_key
35
- fetch_info.primary_key
47
+ def indexes_path(id: nil)
48
+ "/indexes/#{id}"
36
49
  end
37
- alias get_primary_key fetch_primary_key
50
+ private :indexes_path
51
+
52
+ def set_base_properties(index_hash)
53
+ @primary_key = index_hash['primaryKey']
54
+ @created_at = Time.parse(index_hash['createdAt'])
55
+ @updated_at = Time.parse(index_hash['updatedAt'])
56
+ end
57
+ private :set_base_properties
38
58
 
39
59
  ### DOCUMENTS
40
60
 
@@ -46,7 +66,7 @@ module MeiliSearch
46
66
  alias get_one_document document
47
67
 
48
68
  def documents(options = {})
49
- http_get "/indexes/#{@uid}/documents", options
69
+ http_get "/indexes/#{@uid}/documents", Utils.transform_attributes(options)
50
70
  end
51
71
  alias get_documents documents
52
72
 
@@ -76,6 +96,40 @@ module MeiliSearch
76
96
  end
77
97
  alias add_or_update_documents! update_documents!
78
98
 
99
+ def add_documents_in_batches(documents, batch_size = 1000, primary_key = nil)
100
+ update_ids = []
101
+ documents.each_slice(batch_size) do |batch|
102
+ update_ids.append(add_documents(batch, primary_key))
103
+ end
104
+ update_ids
105
+ end
106
+
107
+ def add_documents_in_batches!(documents, batch_size = 1000, primary_key = nil)
108
+ update_ids = add_documents_in_batches(documents, batch_size, primary_key)
109
+ responses = []
110
+ update_ids.each do |update_object|
111
+ responses.append(wait_for_pending_update(update_object['updateId']))
112
+ end
113
+ responses
114
+ end
115
+
116
+ def update_documents_in_batches(documents, batch_size = 1000, primary_key = nil)
117
+ update_ids = []
118
+ documents.each_slice(batch_size) do |batch|
119
+ update_ids.append(update_documents(batch, primary_key))
120
+ end
121
+ update_ids
122
+ end
123
+
124
+ def update_documents_in_batches!(documents, batch_size = 1000, primary_key = nil)
125
+ update_ids = update_documents_in_batches(documents, batch_size, primary_key)
126
+ responses = []
127
+ update_ids.each do |update_object|
128
+ responses.append(wait_for_pending_update(update_object['updateId']))
129
+ end
130
+ responses
131
+ end
132
+
79
133
  def delete_documents(documents_ids)
80
134
  if documents_ids.is_a?(Array)
81
135
  http_post "/indexes/#{@uid}/documents/delete-batch", documents_ids
@@ -115,8 +169,9 @@ module MeiliSearch
115
169
  ### SEARCH
116
170
 
117
171
  def search(query, options = {})
118
- parsed_options = options.compact
119
- http_post "/indexes/#{@uid}/search", { q: query.to_s }.merge(parsed_options)
172
+ parsed_options = Utils.transform_attributes({ q: query.to_s }.merge(options.compact))
173
+
174
+ http_post "/indexes/#{@uid}/search", parsed_options
120
175
  end
121
176
 
122
177
  ### UPDATES
@@ -129,11 +184,15 @@ module MeiliSearch
129
184
  http_get "/indexes/#{@uid}/updates"
130
185
  end
131
186
 
187
+ def achieved_upate?(update)
188
+ update['status'] != 'enqueued' && update['status'] != 'processing'
189
+ end
190
+
132
191
  def wait_for_pending_update(update_id, timeout_in_ms = 5000, interval_in_ms = 50)
133
192
  Timeout.timeout(timeout_in_ms.to_f / 1000) do
134
193
  loop do
135
194
  get_update = get_update_status(update_id)
136
- return get_update if get_update['status'] != 'enqueued'
195
+ return get_update if achieved_upate?(get_update)
137
196
 
138
197
  sleep interval_in_ms.to_f / 1000
139
198
  end
@@ -160,8 +219,8 @@ module MeiliSearch
160
219
  stats['lastUpdate']
161
220
  end
162
221
 
163
- def fields_distribution
164
- stats['fieldsDistribution']
222
+ def field_distribution
223
+ stats['fieldDistribution']
165
224
  end
166
225
 
167
226
  ### SETTINGS - GENERAL
@@ -172,7 +231,7 @@ module MeiliSearch
172
231
  alias get_settings settings
173
232
 
174
233
  def update_settings(settings)
175
- http_post "/indexes/#{@uid}/settings", settings
234
+ http_post "/indexes/#{@uid}/settings", Utils.transform_attributes(settings)
176
235
  end
177
236
  alias settings= update_settings
178
237
 
@@ -220,7 +279,7 @@ module MeiliSearch
220
279
  alias get_stop_words stop_words
221
280
 
222
281
  def update_stop_words(stop_words)
223
- body = stop_words.is_a?(Array) ? stop_words : [stop_words]
282
+ body = stop_words.nil? || stop_words.is_a?(Array) ? stop_words : [stop_words]
224
283
  http_post "/indexes/#{@uid}/settings/stop-words", body
225
284
  end
226
285
  alias stop_words= update_stop_words
@@ -277,20 +336,36 @@ module MeiliSearch
277
336
  http_delete "/indexes/#{@uid}/settings/displayed-attributes"
278
337
  end
279
338
 
280
- ### SETTINGS - ATTRIBUTES FOR FACETING
339
+ ### SETTINGS - FILTERABLE ATTRIBUTES
340
+
341
+ def filterable_attributes
342
+ http_get "/indexes/#{@uid}/settings/filterable-attributes"
343
+ end
344
+ alias get_filterable_attributes filterable_attributes
345
+
346
+ def update_filterable_attributes(filterable_attributes)
347
+ http_post "/indexes/#{@uid}/settings/filterable-attributes", filterable_attributes
348
+ end
349
+ alias filterable_attributes= update_filterable_attributes
350
+
351
+ def reset_filterable_attributes
352
+ http_delete "/indexes/#{@uid}/settings/filterable-attributes"
353
+ end
354
+
355
+ ### SETTINGS - SORTABLE ATTRIBUTES
281
356
 
282
- def attributes_for_faceting
283
- http_get "/indexes/#{@uid}/settings/attributes-for-faceting"
357
+ def sortable_attributes
358
+ http_get "/indexes/#{@uid}/settings/sortable-attributes"
284
359
  end
285
- alias get_attributes_for_faceting attributes_for_faceting
360
+ alias get_sortable_attributes sortable_attributes
286
361
 
287
- def update_attributes_for_faceting(attributes_for_faceting)
288
- http_post "/indexes/#{@uid}/settings/attributes-for-faceting", attributes_for_faceting
362
+ def update_sortable_attributes(sortable_attributes)
363
+ http_post "/indexes/#{@uid}/settings/sortable-attributes", sortable_attributes
289
364
  end
290
- alias attributes_for_faceting= update_attributes_for_faceting
365
+ alias sortable_attributes= update_sortable_attributes
291
366
 
292
- def reset_attributes_for_faceting
293
- http_delete "/indexes/#{@uid}/settings/attributes-for-faceting"
367
+ def reset_sortable_attributes
368
+ http_delete "/indexes/#{@uid}/settings/sortable-attributes"
294
369
  end
295
370
  end
296
371
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MeiliSearch
4
- VERSION = '0.15.4'
4
+ VERSION = '0.17.1'
5
5
  end
data/lib/meilisearch.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'meilisearch/version'
4
+ require 'meilisearch/utils'
4
5
  require 'meilisearch/client'
5
6
  require 'meilisearch/index'
6
7
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meilisearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.15.4
4
+ version: 0.17.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Meili
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-06-11 00:00:00.000000000 Z
11
+ date: 2021-11-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 0.17.1
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 0.19.0
22
+ version: 0.21.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 0.17.1
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.19.0
32
+ version: 0.21.0
33
33
  description: An easy-to-use ruby client for Meilisearch API. See https://github.com/meilisearch/MeiliSearch
34
34
  email: bonjour@meilisearch.com
35
35
  executables: []