meilisearch 0.16.0 → 0.17.2

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: c67baca928880c0efd95580e84a4b3f11f8fbab279a8eec5e6a7ffd64467ce85
4
- data.tar.gz: ee39b314f6607c5ccd219d16bb6e0cb88d971b7113fa1c9091b11634b34e5062
3
+ metadata.gz: 276a1136bc7d85d5c0eaafa7475732990502af66a37859589dea606cffde3c97
4
+ data.tar.gz: e45996c09a5140cf5c66c9f1e30163ca91f37e3e469c00d396c88c318b9541ca
5
5
  SHA512:
6
- metadata.gz: aa7d0a46d608c88ac58786f70d95001c845123c5df29fe3644ddfe8669f87744102076a6610b993b05dd733512922def3ece255fcd562dac103696f07c779a66
7
- data.tar.gz: e6b254f4fc93e8e9f4a0f6aa8df701fbd30cc6565021c0c61f81e709fc96b3423ca0eb4cc6097eb2abba91c76ea6298128e4765c9f2f1f3ce58ba807a8d93bb7
6
+ metadata.gz: '09377cb9cd2eba0800459c57c229db29b9d497716248141125067b97026dabce8f1a6725b0a66336b98700e6cead512c0879e3d5162f402d04fd65277e373711'
7
+ data.tar.gz: 62f69c26b9516074cff7e97a4dde7a45261f511d762aef0ecbd933a5810b4ed3ec4136bb6ef3a9f0b04f9d6dd22699453a823014dd203a172d83d5bbc52f7993
@@ -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
@@ -176,7 +231,7 @@ module MeiliSearch
176
231
  alias get_settings settings
177
232
 
178
233
  def update_settings(settings)
179
- http_post "/indexes/#{@uid}/settings", settings
234
+ http_post "/indexes/#{@uid}/settings", Utils.transform_attributes(settings)
180
235
  end
181
236
  alias settings= update_settings
182
237
 
@@ -296,5 +351,21 @@ module MeiliSearch
296
351
  def reset_filterable_attributes
297
352
  http_delete "/indexes/#{@uid}/settings/filterable-attributes"
298
353
  end
354
+
355
+ ### SETTINGS - SORTABLE ATTRIBUTES
356
+
357
+ def sortable_attributes
358
+ http_get "/indexes/#{@uid}/settings/sortable-attributes"
359
+ end
360
+ alias get_sortable_attributes sortable_attributes
361
+
362
+ def update_sortable_attributes(sortable_attributes)
363
+ http_post "/indexes/#{@uid}/settings/sortable-attributes", sortable_attributes
364
+ end
365
+ alias sortable_attributes= update_sortable_attributes
366
+
367
+ def reset_sortable_attributes
368
+ http_delete "/indexes/#{@uid}/settings/sortable-attributes"
369
+ end
299
370
  end
300
371
  end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MeiliSearch
4
+ module Utils
5
+ SNAKE_CASE = /[^a-zA-Z0-9]+(.)/.freeze
6
+
7
+ def self.transform_attributes(body)
8
+ case body
9
+ when Array
10
+ body.map { |item| transform_attributes(item) }
11
+ when Hash
12
+ parse(body)
13
+ else
14
+ body
15
+ end
16
+ end
17
+
18
+ def self.parse(body)
19
+ body
20
+ .transform_keys(&:to_s)
21
+ .transform_keys do |key|
22
+ key.include?('_') ? key.downcase.gsub(SNAKE_CASE, &:upcase).gsub('_', '') : key
23
+ end
24
+ end
25
+
26
+ private_class_method :parse
27
+ end
28
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MeiliSearch
4
- VERSION = '0.16.0'
4
+ VERSION = '0.17.2'
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.16.0
4
+ version: 0.17.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Meili
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-08-24 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: []
@@ -41,6 +41,7 @@ files:
41
41
  - lib/meilisearch/error.rb
42
42
  - lib/meilisearch/http_request.rb
43
43
  - lib/meilisearch/index.rb
44
+ - lib/meilisearch/utils.rb
44
45
  - lib/meilisearch/version.rb
45
46
  homepage: https://github.com/meilisearch/meilisearch-ruby
46
47
  licenses: