meilisearch 0.16.1 → 0.17.0

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: 5c898ee113e0f0a16da0b80ab6b0a079021eaa8ead536da8dfe283b7613dc27a
4
- data.tar.gz: 29eed6b1c4a3de9efbe54dd766718d70699c5dca5c31dab5b2f901bc5a48c68c
3
+ metadata.gz: c6e2e138205c88de9e5a82459a9a9648c1170380eb977ca839b8ed25aa238a8f
4
+ data.tar.gz: 642d60688d0000f6ae2d6f2ea64de47236eff9af6b34d71ec5bde38a2e76cc83
5
5
  SHA512:
6
- metadata.gz: a005a9271b2f926746fee1294a467f2d319af5bbd75677c3532ec4ec2fe6337ac970eda70e55cbaf6584b98235b8e27801088bfa5aff96d111251ce1b5f426a6
7
- data.tar.gz: 55fc4b9f2754928d72251c4f88ff5dbb6534d9a209eaa3b1ce5bfd5a39941640f68b3a9c2058eecb0396693bc4b0dfa8708f8c9420700ddd56cd4a40578392e3
6
+ metadata.gz: 76f796decd057670599f0cbd8e3c921f73457717b0e49e4a58ee9a7faabbefeae5819ba701c59aff27b4bd22fe449d60623b68e7be47e99d70379caa140097c1
7
+ data.tar.gz: 43734101c23e8fd5ab2fcf1b8044b5005b4e809f9947e16519e0f099e82491e75cce33499329faffb73fec91a589bf5de776566498b2c53054c793cbee7f0891
@@ -6,8 +6,14 @@ 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:
@@ -34,6 +40,17 @@ module MeiliSearch
34
40
  index_object(index_uid).delete
35
41
  end
36
42
 
43
+ # Usage:
44
+ # client.delete_index_if_exists('indexUID')
45
+ def delete_index_if_exists(index_uid)
46
+ index_object(index_uid).delete
47
+ true
48
+ rescue ApiError => e
49
+ raise e if e.code != 'index_not_found'
50
+
51
+ false
52
+ end
53
+
37
54
  # Usage:
38
55
  # client.index('indexUID')
39
56
  def index(index_uid)
@@ -44,6 +61,10 @@ module MeiliSearch
44
61
  index_object(index_uid).fetch_info
45
62
  end
46
63
 
64
+ def fetch_raw_index(index_uid)
65
+ index_object(index_uid).fetch_raw_info
66
+ end
67
+
47
68
  ### KEYS
48
69
 
49
70
  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,26 @@ 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
+ SNAKE_CASE = /[^a-zA-Z0-9]+(.)/.freeze
65
+
66
+ def send_request(http_method, relative_path, query_params: nil, body: nil, headers: nil)
67
+ config = http_config(query_params, body, headers)
59
68
  begin
60
69
  response = http_method.call(@base_url + relative_path, config)
61
70
  rescue Errno::ECONNREFUSED => e
@@ -64,10 +73,10 @@ module MeiliSearch
64
73
  validate(response)
65
74
  end
66
75
 
67
- def http_config(query_params, body)
68
- body = body.to_json
76
+ def http_config(query_params, body, headers)
77
+ body = transform_attributes(body).to_json
69
78
  {
70
- headers: @headers,
79
+ headers: headers,
71
80
  query: query_params,
72
81
  body: body,
73
82
  timeout: @options[:timeout] || 1,
@@ -75,6 +84,25 @@ module MeiliSearch
75
84
  }.compact
76
85
  end
77
86
 
87
+ def transform_attributes(body)
88
+ case body
89
+ when Array
90
+ body.map { |item| transform_attributes(item) }
91
+ when Hash
92
+ parse(body)
93
+ else
94
+ body
95
+ end
96
+ end
97
+
98
+ def parse(body)
99
+ body
100
+ .transform_keys(&:to_s)
101
+ .transform_keys do |key|
102
+ key.include?('_') ? key.downcase.gsub(SNAKE_CASE, &:upcase).gsub('_', '') : key
103
+ end
104
+ end
105
+
78
106
  def validate(response)
79
107
  raise ApiError.new(response.code, response.message, response.body) unless response.success?
80
108
 
@@ -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,46 @@ 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), body
35
+ set_base_properties index_hash
25
36
  self
26
37
  end
38
+
27
39
  alias update_index update
28
40
 
29
41
  def delete
30
- http_delete "/indexes/#{@uid}"
42
+ http_delete indexes_path(id: @uid)
31
43
  end
32
44
  alias delete_index delete
33
45
 
34
- def fetch_primary_key
35
- fetch_info.primary_key
46
+ def indexes_path(id: nil)
47
+ "/indexes/#{id}"
36
48
  end
37
- alias get_primary_key fetch_primary_key
49
+ private :indexes_path
50
+
51
+ def set_base_properties(index_hash)
52
+ @primary_key = index_hash['primaryKey']
53
+ @created_at = Time.parse(index_hash['createdAt'])
54
+ @updated_at = Time.parse(index_hash['updatedAt'])
55
+ end
56
+ private :set_base_properties
38
57
 
39
58
  ### DOCUMENTS
40
59
 
@@ -76,6 +95,40 @@ module MeiliSearch
76
95
  end
77
96
  alias add_or_update_documents! update_documents!
78
97
 
98
+ def add_documents_in_batches(documents, batch_size = 1000, primary_key = nil)
99
+ update_ids = []
100
+ documents.each_slice(batch_size) do |batch|
101
+ update_ids.append(add_documents(batch, primary_key))
102
+ end
103
+ update_ids
104
+ end
105
+
106
+ def add_documents_in_batches!(documents, batch_size = 1000, primary_key = nil)
107
+ update_ids = add_documents_in_batches(documents, batch_size, primary_key)
108
+ responses = []
109
+ update_ids.each do |update_object|
110
+ responses.append(wait_for_pending_update(update_object['updateId']))
111
+ end
112
+ responses
113
+ end
114
+
115
+ def update_documents_in_batches(documents, batch_size = 1000, primary_key = nil)
116
+ update_ids = []
117
+ documents.each_slice(batch_size) do |batch|
118
+ update_ids.append(update_documents(batch, primary_key))
119
+ end
120
+ update_ids
121
+ end
122
+
123
+ def update_documents_in_batches!(documents, batch_size = 1000, primary_key = nil)
124
+ update_ids = update_documents_in_batches(documents, batch_size, primary_key)
125
+ responses = []
126
+ update_ids.each do |update_object|
127
+ responses.append(wait_for_pending_update(update_object['updateId']))
128
+ end
129
+ responses
130
+ end
131
+
79
132
  def delete_documents(documents_ids)
80
133
  if documents_ids.is_a?(Array)
81
134
  http_post "/indexes/#{@uid}/documents/delete-batch", documents_ids
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MeiliSearch
4
- VERSION = '0.16.1'
4
+ VERSION = '0.17.0'
5
5
  end
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.1
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Meili
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-13 00:00:00.000000000 Z
11
+ date: 2021-11-17 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.20.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.20.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: []