meilisearch 0.30.0 → 0.32.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 +4 -4
- data/lib/meilisearch/client.rb +317 -8
- data/lib/meilisearch/http_request.rb +39 -20
- data/lib/meilisearch/index.rb +92 -12
- data/lib/meilisearch/models/task.rb +19 -1
- data/lib/meilisearch/multi_search.rb +13 -3
- data/lib/meilisearch/task.rb +13 -1
- data/lib/meilisearch/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 10979c6d34127afb63d73049967287282428a19ae0d0da81e318ebecbdd5061a
|
4
|
+
data.tar.gz: 5ab882422d999ad86bba6b7b4278b511ca63e47292b9a02c2d3ee62adcecb1a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9dfc97758734f2501107df819bb4a2a260af515acce221726a042dc193f3cd1abc3a7d7eaed0cdd218c549aad6b63fc6d661940fc7395fa6180a5d5293844c0
|
7
|
+
data.tar.gz: 370ceb4c95bfa7bc3df49a780edc030d22469898cc325eba7a00db6d2275a39c1af98e49cf77ea4779d9823768d7b79b851449930e9c73d8d526cec8948a1a3e
|
data/lib/meilisearch/client.rb
CHANGED
@@ -1,18 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Meilisearch
|
4
|
+
# Manages a connection to a Meilisearch server.
|
5
|
+
# client = Meilisearch::Client.new(MEILISEARCH_URL, MASTER_KEY, options)
|
6
|
+
#
|
7
|
+
# @see #indexes Managing search indexes
|
8
|
+
# @see #keys Managing API keys
|
9
|
+
# @see #stats View usage statistics
|
10
|
+
# @see #tasks Managing ongoing tasks
|
11
|
+
# @see #health Health checking
|
12
|
+
# @see #create_dump
|
13
|
+
# @see #create_snapshot
|
4
14
|
class Client < HTTPRequest
|
5
15
|
include Meilisearch::TenantToken
|
6
16
|
include Meilisearch::MultiSearch
|
7
17
|
|
8
18
|
### INDEXES
|
9
19
|
|
20
|
+
# Fetch indexes in instance, returning the raw server response.
|
21
|
+
#
|
22
|
+
# Unless you have a good reason to, {#indexes} should be used instead.
|
23
|
+
#
|
24
|
+
# @see #indexes
|
25
|
+
# @see https://www.meilisearch.com/docs/reference/api/indexes#list-all-indexes Meilisearch API reference
|
26
|
+
# @param options [Hash{Symbol => Object}] limit and offset options
|
27
|
+
# @return [Hash{String => Object}]
|
28
|
+
# {index response object}[https://www.meilisearch.com/docs/reference/api/indexes#response]
|
10
29
|
def raw_indexes(options = {})
|
11
30
|
body = Utils.transform_attributes(options.transform_keys(&:to_sym).slice(:limit, :offset))
|
12
31
|
|
13
32
|
http_get('/indexes', body)
|
14
33
|
end
|
15
34
|
|
35
|
+
# Swap two indexes.
|
36
|
+
#
|
37
|
+
# Can be used as a convenient way to rebuild an index while keeping it operational.
|
38
|
+
# client.index('a_swap').add_documents({})
|
39
|
+
# client.swap_indexes(['a', 'a_swap'])
|
40
|
+
#
|
41
|
+
# Multiple swaps may be done with one request:
|
42
|
+
# client.swap_indexes(['a', 'a_swap'], ['b', 'b_swap'])
|
43
|
+
#
|
44
|
+
# @see https://www.meilisearch.com/docs/reference/api/indexes#swap-indexes Meilisearch API reference
|
45
|
+
#
|
46
|
+
# @param options [Array<Array(String, String)>] the indexes to swap
|
47
|
+
# @return [Models::Task] the async task that swaps the indexes
|
48
|
+
# @raise [ApiError]
|
16
49
|
def swap_indexes(*options)
|
17
50
|
mapped_array = options.map { |arr| { indexes: arr } }
|
18
51
|
|
@@ -20,6 +53,13 @@ module Meilisearch
|
|
20
53
|
Models::Task.new(response, task_endpoint)
|
21
54
|
end
|
22
55
|
|
56
|
+
# Fetch indexes in instance.
|
57
|
+
#
|
58
|
+
# @see https://www.meilisearch.com/docs/reference/api/indexes#list-all-indexes Meilisearch API reference
|
59
|
+
# @param options [Hash{Symbol => Object}] limit and offset options
|
60
|
+
# @return [Hash{String => Object}]
|
61
|
+
# {index response object}[https://www.meilisearch.com/docs/reference/api/indexes#response]
|
62
|
+
# with results mapped to instances of {Index}
|
23
63
|
def indexes(options = {})
|
24
64
|
response = raw_indexes(options)
|
25
65
|
|
@@ -30,9 +70,23 @@ module Meilisearch
|
|
30
70
|
response
|
31
71
|
end
|
32
72
|
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
73
|
+
# Create a new empty index.
|
74
|
+
#
|
75
|
+
# client.create_index('indexUID')
|
76
|
+
# client.create_index('indexUID', primary_key: 'id')
|
77
|
+
#
|
78
|
+
# Indexes are also created when accessed:
|
79
|
+
#
|
80
|
+
# client.index('new_index').add_documents({})
|
81
|
+
#
|
82
|
+
# @see #index
|
83
|
+
# @see https://www.meilisearch.com/docs/reference/api/indexes#create-an-index Meilisearch API reference
|
84
|
+
#
|
85
|
+
# @param index_uid [String] the uid of the new index
|
86
|
+
# @param options [Hash{Symbol => Object}, nil] snake_cased options of {the endpoint}[https://www.meilisearch.com/docs/reference/api/indexes#create-an-index]
|
87
|
+
#
|
88
|
+
# @raise [ApiError]
|
89
|
+
# @return [Models::Task] the async task that creates the index
|
36
90
|
def create_index(index_uid, options = {})
|
37
91
|
body = Utils.transform_attributes(options.merge(uid: index_uid))
|
38
92
|
|
@@ -41,8 +95,14 @@ module Meilisearch
|
|
41
95
|
Models::Task.new(response, task_endpoint)
|
42
96
|
end
|
43
97
|
|
44
|
-
# Synchronous version of create_index.
|
45
|
-
#
|
98
|
+
# Synchronous version of {#create_index}.
|
99
|
+
#
|
100
|
+
# @deprecated
|
101
|
+
# use {Models::Task#await} on task returned from {#create_index}
|
102
|
+
#
|
103
|
+
# client.create_index('foo').await
|
104
|
+
#
|
105
|
+
# Waits for the task to be achieved with a busy loop, be careful when using it.
|
46
106
|
def create_index!(index_uid, options = {})
|
47
107
|
Utils.soft_deprecate(
|
48
108
|
'Client#create_index!',
|
@@ -52,42 +112,131 @@ module Meilisearch
|
|
52
112
|
create_index(index_uid, options).await
|
53
113
|
end
|
54
114
|
|
115
|
+
# Delete an index.
|
116
|
+
#
|
117
|
+
# @param index_uid [String] the uid of the index to be deleted
|
118
|
+
# @return [Models::Task] the async task deleting the index
|
55
119
|
def delete_index(index_uid)
|
56
120
|
index_object(index_uid).delete
|
57
121
|
end
|
58
122
|
|
59
|
-
#
|
60
|
-
#
|
123
|
+
# Get index with given uid.
|
124
|
+
#
|
125
|
+
# Indexes that don't exist are lazily created by Meilisearch.
|
126
|
+
# index = client.index('index_uid')
|
127
|
+
# index.add_documents({}) # index is created here if it did not exist
|
128
|
+
#
|
129
|
+
# @see Index
|
130
|
+
# @param index_uid [String] the uid of the index to get
|
131
|
+
# @return [Index]
|
61
132
|
def index(index_uid)
|
62
133
|
index_object(index_uid)
|
63
134
|
end
|
64
135
|
|
136
|
+
# Shorthand for
|
137
|
+
# client.index(index_uid).fetch_info
|
138
|
+
#
|
139
|
+
# @see Index#fetch_info
|
140
|
+
# @param index_uid [String] uid of the index
|
65
141
|
def fetch_index(index_uid)
|
66
142
|
index_object(index_uid).fetch_info
|
67
143
|
end
|
68
144
|
|
145
|
+
# Shorthand for
|
146
|
+
# client.index(index_uid).fetch_raw_info
|
147
|
+
#
|
148
|
+
# @see Index#fetch_raw_info
|
149
|
+
# @param index_uid [String] uid of the index
|
69
150
|
def fetch_raw_index(index_uid)
|
70
151
|
index_object(index_uid).fetch_raw_info
|
71
152
|
end
|
72
153
|
|
73
154
|
### KEYS
|
74
155
|
|
156
|
+
# Get all API keys
|
157
|
+
#
|
158
|
+
# This and other key methods require that the Meilisearch instance have a
|
159
|
+
# {master key}[https://www.meilisearch.com/docs/learn/security/differences_master_api_keys#master-key]
|
160
|
+
# set.
|
161
|
+
#
|
162
|
+
# @see #create_key #create_key to create keys and set their scope
|
163
|
+
# @see #key #key to fetch one key
|
164
|
+
# @see https://www.meilisearch.com/docs/reference/api/keys#get-all-keys Meilisearch API reference
|
165
|
+
# @param limit [String, Integer, nil] limit the number of returned keys
|
166
|
+
# @param offset [String, Integer, nil] skip the first +offset+ keys,
|
167
|
+
# useful for paging.
|
168
|
+
#
|
169
|
+
# @return [Hash{String => Object}] a {keys response}[https://www.meilisearch.com/docs/reference/api/keys#response]
|
75
170
|
def keys(limit: nil, offset: nil)
|
76
171
|
body = { limit: limit, offset: offset }.compact
|
77
172
|
|
78
173
|
http_get '/keys', body
|
79
174
|
end
|
80
175
|
|
176
|
+
# Get a specific API key.
|
177
|
+
#
|
178
|
+
# # obviously this example uid will not correspond to a key on your server
|
179
|
+
# # please replace it with your own key's uid
|
180
|
+
# uid = '6062abda-a5aa-4414-ac91-ecd7944c0f8d'
|
181
|
+
# client.key(uid)
|
182
|
+
#
|
183
|
+
# This and other key methods require that the Meilisearch instance have a
|
184
|
+
# {master key}[https://www.meilisearch.com/docs/learn/security/differences_master_api_keys#master-key]
|
185
|
+
# set.
|
186
|
+
#
|
187
|
+
# @see #keys #keys to get all keys in the instance
|
188
|
+
# @see #create_key #create_key to create keys and set their scope
|
189
|
+
# @see https://www.meilisearch.com/docs/reference/api/keys#get-one-key Meilisearch API reference
|
190
|
+
# @param uid_or_key [String] either the uuidv4 that is the key's
|
191
|
+
# {uid}[https://www.meilisearch.com/docs/reference/api/keys#uid] or
|
192
|
+
# a hash of the uid and the master key that is the key's
|
193
|
+
# {key}[https://www.meilisearch.com/docs/reference/api/keys#key] field
|
194
|
+
#
|
195
|
+
# @return [Hash{String => Object}] a {key object}[https://www.meilisearch.com/docs/reference/api/keys#key-object]
|
81
196
|
def key(uid_or_key)
|
82
197
|
http_get "/keys/#{uid_or_key}"
|
83
198
|
end
|
84
199
|
|
200
|
+
# Create a new API key.
|
201
|
+
#
|
202
|
+
# require 'date_core'
|
203
|
+
# ten_days_later = (DateTime.now + 10).rfc3339
|
204
|
+
# client.create_key(actions: ['*'], indexes: ['*'], expires_at: ten_days_later)
|
205
|
+
#
|
206
|
+
# This and other key methods require that the Meilisearch instance have a
|
207
|
+
# {master key}[https://www.meilisearch.com/docs/learn/security/differences_master_api_keys#master-key]
|
208
|
+
# set.
|
209
|
+
#
|
210
|
+
# @see #update_key #update_key to edit an existing key
|
211
|
+
# @see #keys #keys to get all keys in the instance
|
212
|
+
# @see #key #key to fetch one key
|
213
|
+
# @see https://www.meilisearch.com/docs/reference/api/keys#create-a-key Meilisearch API reference
|
214
|
+
# @param key_options [Hash{Symbol => Object}] the key options of which the required are
|
215
|
+
# - +:actions+ +Array+ of API actions allowed for key, +["*"]+ for all
|
216
|
+
# - +:indexes+ +Array+ of indexes key can act on, +["*"]+ for all
|
217
|
+
# - +:expires_at+ expiration datetime in
|
218
|
+
# {RFC 3339}[https://www.ietf.org/rfc/rfc3339.txt] format, nil if the key never expires
|
219
|
+
#
|
220
|
+
# @return [Hash{String => Object}] a {key object}[https://www.meilisearch.com/docs/reference/api/keys#key-object]
|
85
221
|
def create_key(key_options)
|
86
222
|
body = Utils.transform_attributes(key_options)
|
87
223
|
|
88
224
|
http_post '/keys', body
|
89
225
|
end
|
90
226
|
|
227
|
+
# Update an existing API key.
|
228
|
+
#
|
229
|
+
# This and other key methods require that the Meilisearch instance have a
|
230
|
+
# {master key}[https://www.meilisearch.com/docs/learn/security/differences_master_api_keys#master-key]
|
231
|
+
# set.
|
232
|
+
#
|
233
|
+
# @see #create_key #create_key to create a new key
|
234
|
+
# @see #keys #keys to get all keys in the instance
|
235
|
+
# @see #key #key to fetch one key
|
236
|
+
# @see https://www.meilisearch.com/docs/reference/api/keys#update-a-key Meilisearch API reference
|
237
|
+
# @param key_options [Hash{Symbol => Object}] see {#create_key}
|
238
|
+
#
|
239
|
+
# @return [Hash{String => Object}] a {key object}[https://www.meilisearch.com/docs/reference/api/keys#key-object]
|
91
240
|
def update_key(uid_or_key, key_options)
|
92
241
|
body = Utils.transform_attributes(key_options)
|
93
242
|
body = body.slice('description', 'name')
|
@@ -95,12 +244,34 @@ module Meilisearch
|
|
95
244
|
http_patch "/keys/#{uid_or_key}", body
|
96
245
|
end
|
97
246
|
|
247
|
+
# Delete an API key.
|
248
|
+
#
|
249
|
+
# # obviously this example uid will not correspond to a key on your server
|
250
|
+
# # please replace it with your own key's uid
|
251
|
+
# uid = '6062abda-a5aa-4414-ac91-ecd7944c0f8d'
|
252
|
+
# client.delete_key(uid)
|
253
|
+
#
|
254
|
+
# This and other key methods require that the Meilisearch instance have a
|
255
|
+
# {master key}[https://www.meilisearch.com/docs/learn/security/differences_master_api_keys#master-key]
|
256
|
+
# set.
|
257
|
+
#
|
258
|
+
# @see #keys #keys to get all keys in the instance
|
259
|
+
# @see #create_key #create_key to create keys and set their scope
|
260
|
+
# @see https://www.meilisearch.com/docs/reference/api/keys#delete-a-key Meilisearch API reference
|
261
|
+
# @param uid_or_key [String] either the uuidv4 that is the key's
|
262
|
+
# {uid}[https://www.meilisearch.com/docs/reference/api/keys#uid] or
|
263
|
+
# a hash of the uid and the master key that is the key's
|
264
|
+
# {key}[https://www.meilisearch.com/docs/reference/api/keys#key] field
|
98
265
|
def delete_key(uid_or_key)
|
99
266
|
http_delete "/keys/#{uid_or_key}"
|
100
267
|
end
|
101
268
|
|
102
269
|
### HEALTH
|
103
270
|
|
271
|
+
# Check if Meilisearch instance is healthy.
|
272
|
+
#
|
273
|
+
# @see #health
|
274
|
+
# @return [bool] whether or not the +/health+ endpoint raises any errors
|
104
275
|
def healthy?
|
105
276
|
http_get '/health'
|
106
277
|
true
|
@@ -108,22 +279,51 @@ module Meilisearch
|
|
108
279
|
false
|
109
280
|
end
|
110
281
|
|
282
|
+
# Check health of Meilisearch instance.
|
283
|
+
#
|
284
|
+
# @see https://www.meilisearch.com/docs/reference/api/health#get-health Meilisearch API reference
|
285
|
+
# @return [Hash{String => Object}] the health report from the Meilisearch instance
|
111
286
|
def health
|
112
287
|
http_get '/health'
|
113
288
|
end
|
114
289
|
|
115
290
|
### STATS
|
116
291
|
|
292
|
+
# Check version of Meilisearch server
|
293
|
+
#
|
294
|
+
# @see https://www.meilisearch.com/docs/reference/api/version#get-version-of-meilisearch Meilisearch API reference
|
295
|
+
# @return [Hash{String => String}] package version and last commit of Meilisearch server, see
|
296
|
+
# {version object}[https://www.meilisearch.com/docs/reference/api/version#version-object]
|
117
297
|
def version
|
118
298
|
http_get '/version'
|
119
299
|
end
|
120
300
|
|
301
|
+
# Get stats of all indexes in instance.
|
302
|
+
#
|
303
|
+
# @see Index#stats
|
304
|
+
# @see https://www.meilisearch.com/docs/reference/api/stats#get-stats-of-all-indexes Meilisearch API reference
|
305
|
+
# @return [Hash{String => Object}] see {stats object}[https://www.meilisearch.com/docs/reference/api/stats#stats-object]
|
121
306
|
def stats
|
122
307
|
http_get '/stats'
|
123
308
|
end
|
124
309
|
|
125
310
|
### DUMPS
|
126
311
|
|
312
|
+
# Create a database dump.
|
313
|
+
#
|
314
|
+
# Dumps are "blueprints" which can be used to restore your database. Restoring
|
315
|
+
# a dump requires reindexing all documents and is therefore inefficient.
|
316
|
+
#
|
317
|
+
# Dumps are created by the Meilisearch server in the directory where the server is started
|
318
|
+
# under +dumps/+ by default.
|
319
|
+
#
|
320
|
+
# @see https://www.meilisearch.com/docs/learn/advanced/snapshots_vs_dumps
|
321
|
+
# The difference between snapshots and dumps
|
322
|
+
# @see https://www.meilisearch.com/docs/learn/advanced/dumps
|
323
|
+
# Meilisearch documentation on how to use dumps
|
324
|
+
# @see https://www.meilisearch.com/docs/reference/api/dump#create-a-dump
|
325
|
+
# Meilisearch API reference
|
326
|
+
# @return [Models::Task] the async task that is creating the dump
|
127
327
|
def create_dump
|
128
328
|
response = http_post '/dumps'
|
129
329
|
Models::Task.new(response, task_endpoint)
|
@@ -131,42 +331,151 @@ module Meilisearch
|
|
131
331
|
|
132
332
|
### SNAPSHOTS
|
133
333
|
|
334
|
+
# Create a database snapshot.
|
335
|
+
#
|
336
|
+
# Snapshots are exact copies of the Meilisearch database. As such they are pre-indexed
|
337
|
+
# and restoring one is a very efficient operation.
|
338
|
+
#
|
339
|
+
# Snapshots are not compatible between Meilisearch versions. Snapshot creation takes priority
|
340
|
+
# over other tasks.
|
341
|
+
#
|
342
|
+
# Snapshots are created by the Meilisearch server in the directory where the server is started
|
343
|
+
# under +snapshots/+ by default.
|
344
|
+
#
|
345
|
+
# @see https://www.meilisearch.com/docs/learn/advanced/snapshots_vs_dumps
|
346
|
+
# The difference between snapshots and dumps
|
347
|
+
# @see https://www.meilisearch.com/docs/learn/advanced/snapshots
|
348
|
+
# Meilisearch documentation on how to use snapshots
|
349
|
+
# @see https://www.meilisearch.com/docs/reference/api/snapshots#create-a-snapshot
|
350
|
+
# Meilisearch API reference
|
351
|
+
# @return [Models::Task] the async task that is creating the snapshot
|
134
352
|
def create_snapshot
|
135
353
|
http_post '/snapshots'
|
136
354
|
end
|
137
355
|
|
138
356
|
### TASKS
|
139
357
|
|
358
|
+
# Cancel tasks matching the filter.
|
359
|
+
#
|
360
|
+
# This route is meant to be used with options, please see the API reference.
|
361
|
+
#
|
362
|
+
# Operations in Meilisearch are done asynchronously using "tasks".
|
363
|
+
# Tasks report their progress and status.
|
364
|
+
#
|
365
|
+
# Warning: This does not return instances of {Models::Task}. This is a raw
|
366
|
+
# call to the Meilisearch API and the return is not modified.
|
367
|
+
#
|
368
|
+
# @see https://www.meilisearch.com/docs/reference/api/tasks#task-object The Task Object
|
369
|
+
# @see https://www.meilisearch.com/docs/reference/api/tasks#cancel-tasks Meilisearch API reference
|
370
|
+
# @param options [Hash{Symbol => Object}] task search options as snake cased symbols, see the API reference
|
371
|
+
# @return [Hash{String => Object}] a Meilisearch task that is canceling other tasks
|
140
372
|
def cancel_tasks(options = {})
|
141
373
|
task_endpoint.cancel_tasks(options)
|
142
374
|
end
|
143
375
|
|
376
|
+
# Cancel tasks matching the filter.
|
377
|
+
#
|
378
|
+
# This route is meant to be used with options, please see the API reference.
|
379
|
+
#
|
380
|
+
# Operations in Meilisearch are done asynchronously using "tasks".
|
381
|
+
# Tasks report their progress and status.
|
382
|
+
#
|
383
|
+
# Warning: This does not return instances of {Models::Task}. This is a raw
|
384
|
+
# call to the Meilisearch API and the return is not modified.
|
385
|
+
#
|
386
|
+
# Tasks are run in batches, see {#batches}.
|
387
|
+
#
|
388
|
+
# @see https://www.meilisearch.com/docs/reference/api/tasks#task-object The Task Object
|
389
|
+
# @see https://www.meilisearch.com/docs/reference/api/tasks#cancel-tasks Meilisearch API reference
|
390
|
+
# @param options [Hash{Symbol => Object}] task search options as snake cased symbols, see the API reference
|
391
|
+
# @return [Hash{String => Object}] a Meilisearch task that is canceling other tasks
|
144
392
|
def delete_tasks(options = {})
|
145
393
|
task_endpoint.delete_tasks(options)
|
146
394
|
end
|
147
395
|
|
396
|
+
# Get Meilisearch tasks matching the filters.
|
397
|
+
#
|
398
|
+
# Operations in Meilisearch are done asynchronously using "tasks".
|
399
|
+
# Tasks report their progress and status.
|
400
|
+
#
|
401
|
+
# Warning: This does not return instances of {Models::Task}. This is a raw
|
402
|
+
# call to the Meilisearch API and the return is not modified.
|
403
|
+
#
|
404
|
+
# @see https://www.meilisearch.com/docs/reference/api/tasks#task-object The Task Object
|
405
|
+
# @see https://www.meilisearch.com/docs/reference/api/tasks#get-tasks Meilisearch API reference
|
406
|
+
# @param options [Hash{Symbol => Object}] task search options as snake cased symbols, see the API reference
|
407
|
+
# @return [Hash{String => Object}] results of the task search, see API reference
|
148
408
|
def tasks(options = {})
|
149
409
|
task_endpoint.task_list(options)
|
150
410
|
end
|
151
411
|
|
412
|
+
# Get one task.
|
413
|
+
#
|
414
|
+
# Operations in Meilisearch are done asynchronously using "tasks".
|
415
|
+
# Tasks report their progress and status.
|
416
|
+
#
|
417
|
+
# Warning: This does not return instances of {Models::Task}. This is a raw
|
418
|
+
# call to the Meilisearch API and the return is not modified.
|
419
|
+
#
|
420
|
+
# @see https://www.meilisearch.com/docs/reference/api/tasks#task-object The Task Object
|
421
|
+
# @see https://www.meilisearch.com/docs/reference/api/tasks#get-one-task Meilisearch API reference
|
422
|
+
# @param task_uid [String] uid of the requested task
|
423
|
+
# @return [Hash{String => Object}] a Meilisearch task object (see above)
|
152
424
|
def task(task_uid)
|
153
425
|
task_endpoint.task(task_uid)
|
154
426
|
end
|
155
427
|
|
156
|
-
|
428
|
+
# Wait for a task in a busy loop.
|
429
|
+
#
|
430
|
+
# Try to avoid using it. Wrapper around {Task#wait_for_task}.
|
431
|
+
# @see Task#wait_for_task
|
432
|
+
def wait_for_task(
|
433
|
+
task_uid,
|
434
|
+
timeout_in_ms = Models::Task.default_timeout_ms,
|
435
|
+
interval_in_ms = Models::Task.default_interval_ms
|
436
|
+
)
|
157
437
|
task_endpoint.wait_for_task(task_uid, timeout_in_ms, interval_in_ms)
|
158
438
|
end
|
159
439
|
|
160
440
|
### BATCHES
|
161
441
|
|
442
|
+
# Get Meilisearch task batches matching the filters.
|
443
|
+
#
|
444
|
+
# Operations in Meilisearch are done asynchronously using "tasks".
|
445
|
+
# Tasks are run in batches.
|
446
|
+
#
|
447
|
+
# @see https://www.meilisearch.com/docs/reference/api/batches#batch-object The Batch Object
|
448
|
+
# @see https://www.meilisearch.com/docs/reference/api/batches#get-batches Meilisearch API reference
|
449
|
+
# @param options [Hash{Symbol => Object}] task search options as snake cased symbols, see the API reference
|
450
|
+
# @return [Hash{String => Object}] results of the batches search, see API reference
|
162
451
|
def batches(options = {})
|
163
452
|
http_get '/batches', options
|
164
453
|
end
|
165
454
|
|
455
|
+
# Get a single Meilisearch task batch matching +batch_uid+.
|
456
|
+
#
|
457
|
+
# Operations in Meilisearch are done asynchronously using "tasks".
|
458
|
+
# Tasks are run in batches.
|
459
|
+
#
|
460
|
+
# @see https://www.meilisearch.com/docs/reference/api/batches#batch-object The Batch Object
|
461
|
+
# @see https://www.meilisearch.com/docs/reference/api/batches#get-one-batch Meilisearch API reference
|
462
|
+
# @param batch_uid [String] the uid of the request batch
|
463
|
+
# @return [Hash{String => Object}] a batch object, see above
|
166
464
|
def batch(batch_uid)
|
167
465
|
http_get "/batches/#{batch_uid}"
|
168
466
|
end
|
169
467
|
|
468
|
+
### EXPERIMENTAL FEATURES
|
469
|
+
|
470
|
+
def experimental_features
|
471
|
+
http_get '/experimental-features'
|
472
|
+
end
|
473
|
+
|
474
|
+
def update_experimental_features(expe_feat_changes)
|
475
|
+
expe_feat_changes = Utils.transform_attributes(expe_feat_changes)
|
476
|
+
http_patch '/experimental-features', expe_feat_changes
|
477
|
+
end
|
478
|
+
|
170
479
|
private
|
171
480
|
|
172
481
|
def index_object(uid, primary_key = nil)
|
@@ -10,8 +10,9 @@ module Meilisearch
|
|
10
10
|
attr_reader :options, :headers
|
11
11
|
|
12
12
|
DEFAULT_OPTIONS = {
|
13
|
-
timeout:
|
14
|
-
max_retries:
|
13
|
+
timeout: 10,
|
14
|
+
max_retries: 2,
|
15
|
+
retry_multiplier: 1.2,
|
15
16
|
convert_body?: true
|
16
17
|
}.freeze
|
17
18
|
|
@@ -22,14 +23,15 @@ module Meilisearch
|
|
22
23
|
@headers = build_default_options_headers
|
23
24
|
end
|
24
25
|
|
25
|
-
def http_get(relative_path = '', query_params = {})
|
26
|
+
def http_get(relative_path = '', query_params = {}, options = {})
|
26
27
|
send_request(
|
27
28
|
proc { |path, config| self.class.get(path, config) },
|
28
29
|
relative_path,
|
29
30
|
config: {
|
30
31
|
query_params: query_params,
|
31
|
-
headers: remove_headers(@headers.dup, 'Content-Type'),
|
32
|
-
options: @options
|
32
|
+
headers: remove_headers(@headers.dup.merge(options[:headers] || {}), 'Content-Type'),
|
33
|
+
options: @options.merge(options),
|
34
|
+
method_type: :get
|
33
35
|
}
|
34
36
|
)
|
35
37
|
end
|
@@ -42,45 +44,49 @@ module Meilisearch
|
|
42
44
|
query_params: query_params,
|
43
45
|
body: body,
|
44
46
|
headers: @headers.dup.merge(options[:headers] || {}),
|
45
|
-
options: @options.merge(options)
|
47
|
+
options: @options.merge(options),
|
48
|
+
method_type: :post
|
46
49
|
}
|
47
50
|
)
|
48
51
|
end
|
49
52
|
|
50
|
-
def http_put(relative_path = '', body = nil, query_params = nil)
|
53
|
+
def http_put(relative_path = '', body = nil, query_params = nil, options = {})
|
51
54
|
send_request(
|
52
55
|
proc { |path, config| self.class.put(path, config) },
|
53
56
|
relative_path,
|
54
57
|
config: {
|
55
58
|
query_params: query_params,
|
56
59
|
body: body,
|
57
|
-
headers: @headers,
|
58
|
-
options: @options
|
60
|
+
headers: @headers.dup.merge(options[:headers] || {}),
|
61
|
+
options: @options.merge(options),
|
62
|
+
method_type: :put
|
59
63
|
}
|
60
64
|
)
|
61
65
|
end
|
62
66
|
|
63
|
-
def http_patch(relative_path = '', body = nil, query_params = nil)
|
67
|
+
def http_patch(relative_path = '', body = nil, query_params = nil, options = {})
|
64
68
|
send_request(
|
65
69
|
proc { |path, config| self.class.patch(path, config) },
|
66
70
|
relative_path,
|
67
71
|
config: {
|
68
72
|
query_params: query_params,
|
69
73
|
body: body,
|
70
|
-
headers: @headers,
|
71
|
-
options: @options
|
74
|
+
headers: @headers.dup.merge(options[:headers] || {}),
|
75
|
+
options: @options.merge(options),
|
76
|
+
method_type: :patch
|
72
77
|
}
|
73
78
|
)
|
74
79
|
end
|
75
80
|
|
76
|
-
def http_delete(relative_path = '', query_params = nil)
|
81
|
+
def http_delete(relative_path = '', query_params = nil, options = {})
|
77
82
|
send_request(
|
78
83
|
proc { |path, config| self.class.delete(path, config) },
|
79
84
|
relative_path,
|
80
85
|
config: {
|
81
86
|
query_params: query_params,
|
82
|
-
headers: remove_headers(@headers.dup, 'Content-Type'),
|
83
|
-
options: @options
|
87
|
+
headers: remove_headers(@headers.dup.merge(options[:headers] || {}), 'Content-Type'),
|
88
|
+
options: @options.merge(options),
|
89
|
+
method_type: :delete
|
84
90
|
}
|
85
91
|
)
|
86
92
|
end
|
@@ -102,15 +108,23 @@ module Meilisearch
|
|
102
108
|
data.delete_if { |k| keys.include?(k) }
|
103
109
|
end
|
104
110
|
|
105
|
-
def send_request(http_method, relative_path, config:
|
106
|
-
|
111
|
+
def send_request(http_method, relative_path, config:)
|
112
|
+
attempts = 0
|
113
|
+
retry_multiplier = config.dig(:options, :retry_multiplier)
|
114
|
+
max_retries = config.dig(:options, :max_retries)
|
115
|
+
request_config = http_config(config[:query_params], config[:body], config[:options], config[:headers])
|
107
116
|
|
108
117
|
begin
|
109
|
-
response = http_method.call(@base_url + relative_path,
|
118
|
+
response = http_method.call(@base_url + relative_path, request_config)
|
110
119
|
rescue Errno::ECONNREFUSED, Errno::EPIPE => e
|
111
120
|
raise CommunicationError, e.message
|
112
|
-
rescue Net::
|
113
|
-
|
121
|
+
rescue Net::OpenTimeout, Net::ReadTimeout => e
|
122
|
+
attempts += 1
|
123
|
+
raise TimeoutError, e.message unless attempts <= max_retries && safe_to_retry?(config[:method_type], e)
|
124
|
+
|
125
|
+
sleep(retry_multiplier**attempts)
|
126
|
+
|
127
|
+
retry
|
114
128
|
end
|
115
129
|
|
116
130
|
validate(response)
|
@@ -132,5 +146,10 @@ module Meilisearch
|
|
132
146
|
|
133
147
|
response.parsed_response
|
134
148
|
end
|
149
|
+
|
150
|
+
# Ensures the only retryable error is a timeout didn't reached the server
|
151
|
+
def safe_to_retry?(method_type, error)
|
152
|
+
method_type == :get || ([:post, :put, :patch, :delete].include?(method_type) && error.is_a?(Net::OpenTimeout))
|
153
|
+
end
|
135
154
|
end
|
136
155
|
end
|
data/lib/meilisearch/index.rb
CHANGED
@@ -145,6 +145,48 @@ module Meilisearch
|
|
145
145
|
end
|
146
146
|
alias add_or_update_documents update_documents
|
147
147
|
|
148
|
+
def update_documents_json(documents, primary_key = nil)
|
149
|
+
options = { convert_body?: false }
|
150
|
+
response = http_put "/indexes/#{@uid}/documents", documents, { primaryKey: primary_key }.compact, options
|
151
|
+
|
152
|
+
Models::Task.new(response, task_endpoint)
|
153
|
+
end
|
154
|
+
alias add_or_update_documents_json update_documents_json
|
155
|
+
|
156
|
+
def update_documents_ndjson(documents, primary_key = nil)
|
157
|
+
options = { headers: { 'Content-Type' => 'application/x-ndjson' }, convert_body?: false }
|
158
|
+
response = http_put "/indexes/#{@uid}/documents", documents, { primaryKey: primary_key }.compact, options
|
159
|
+
|
160
|
+
Models::Task.new(response, task_endpoint)
|
161
|
+
end
|
162
|
+
alias add_or_update_documents_ndjson update_documents_ndjson
|
163
|
+
|
164
|
+
def update_documents_csv(documents, primary_key = nil, delimiter = nil)
|
165
|
+
options = { headers: { 'Content-Type' => 'text/csv' }, convert_body?: false }
|
166
|
+
|
167
|
+
response = http_put "/indexes/#{@uid}/documents", documents, {
|
168
|
+
primaryKey: primary_key,
|
169
|
+
csvDelimiter: delimiter
|
170
|
+
}.compact, options
|
171
|
+
|
172
|
+
Models::Task.new(response, task_endpoint)
|
173
|
+
end
|
174
|
+
alias add_or_update_documents_csv add_documents_csv
|
175
|
+
|
176
|
+
def update_documents_ndjson_in_batches(documents, batch_size = 1000, primary_key = nil)
|
177
|
+
documents.lines.each_slice(batch_size).map do |batch|
|
178
|
+
update_documents_ndjson(batch.join, primary_key)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def update_documents_csv_in_batches(documents, batch_size = 1000, primary_key = nil, delimiter = nil)
|
183
|
+
lines = documents.lines
|
184
|
+
heading = lines.first
|
185
|
+
lines.drop(1).each_slice(batch_size).map do |batch|
|
186
|
+
update_documents_csv(heading + batch.join, primary_key, delimiter)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
148
190
|
def update_documents!(documents, primary_key = nil)
|
149
191
|
Utils.soft_deprecate(
|
150
192
|
'Index#update_documents!',
|
@@ -161,6 +203,20 @@ module Meilisearch
|
|
161
203
|
end
|
162
204
|
end
|
163
205
|
|
206
|
+
def add_documents_ndjson_in_batches(documents, batch_size = 1000, primary_key = nil)
|
207
|
+
documents.lines.each_slice(batch_size).map do |batch|
|
208
|
+
add_documents_ndjson(batch.join, primary_key)
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def add_documents_csv_in_batches(documents, batch_size = 1000, primary_key = nil, delimiter = nil)
|
213
|
+
lines = documents.lines
|
214
|
+
heading = lines.first
|
215
|
+
lines.drop(1).each_slice(batch_size).map do |batch|
|
216
|
+
add_documents_csv(heading + batch.join, primary_key, delimiter)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
164
220
|
def add_documents_in_batches!(documents, batch_size = 1000, primary_key = nil)
|
165
221
|
Utils.soft_deprecate(
|
166
222
|
'Index#add_documents_in_batches!',
|
@@ -609,11 +665,15 @@ module Meilisearch
|
|
609
665
|
end
|
610
666
|
|
611
667
|
def update_proximity_precision(proximity_precision_attribute)
|
612
|
-
http_put("/indexes/#{@uid}/settings/proximity-precision", proximity_precision_attribute)
|
668
|
+
response = http_put("/indexes/#{@uid}/settings/proximity-precision", proximity_precision_attribute)
|
669
|
+
|
670
|
+
Models::Task.new(response, task_endpoint)
|
613
671
|
end
|
614
672
|
|
615
673
|
def reset_proximity_precision
|
616
|
-
http_delete("/indexes/#{@uid}/settings/proximity-precision")
|
674
|
+
response = http_delete("/indexes/#{@uid}/settings/proximity-precision")
|
675
|
+
|
676
|
+
Models::Task.new(response, task_endpoint)
|
617
677
|
end
|
618
678
|
|
619
679
|
### SETTINGS - SEARCH CUTOFF MS
|
@@ -623,11 +683,15 @@ module Meilisearch
|
|
623
683
|
end
|
624
684
|
|
625
685
|
def update_search_cutoff_ms(search_cutoff_ms_attribute)
|
626
|
-
http_put("/indexes/#{@uid}/settings/search-cutoff-ms", search_cutoff_ms_attribute)
|
686
|
+
response = http_put("/indexes/#{@uid}/settings/search-cutoff-ms", search_cutoff_ms_attribute)
|
687
|
+
|
688
|
+
Models::Task.new(response, task_endpoint)
|
627
689
|
end
|
628
690
|
|
629
691
|
def reset_search_cutoff_ms
|
630
|
-
http_delete("/indexes/#{@uid}/settings/search-cutoff-ms")
|
692
|
+
response = http_delete("/indexes/#{@uid}/settings/search-cutoff-ms")
|
693
|
+
|
694
|
+
Models::Task.new(response, task_endpoint)
|
631
695
|
end
|
632
696
|
|
633
697
|
### SETTINGS - LOCALIZED ATTRIBUTES
|
@@ -639,11 +703,15 @@ module Meilisearch
|
|
639
703
|
def update_localized_attributes(new_localized_attributes)
|
640
704
|
new_localized_attributes = Utils.transform_attributes(new_localized_attributes)
|
641
705
|
|
642
|
-
http_put("/indexes/#{@uid}/settings/localized-attributes", new_localized_attributes)
|
706
|
+
response = http_put("/indexes/#{@uid}/settings/localized-attributes", new_localized_attributes)
|
707
|
+
|
708
|
+
Models::Task.new(response, task_endpoint)
|
643
709
|
end
|
644
710
|
|
645
711
|
def reset_localized_attributes
|
646
|
-
http_delete("/indexes/#{@uid}/settings/localized-attributes")
|
712
|
+
response = http_delete("/indexes/#{@uid}/settings/localized-attributes")
|
713
|
+
|
714
|
+
Models::Task.new(response, task_endpoint)
|
647
715
|
end
|
648
716
|
|
649
717
|
### SETTINGS - FACET SEARCH
|
@@ -653,11 +721,15 @@ module Meilisearch
|
|
653
721
|
end
|
654
722
|
|
655
723
|
def update_facet_search_setting(new_facet_search_setting)
|
656
|
-
http_put("/indexes/#{@uid}/settings/facet-search", new_facet_search_setting)
|
724
|
+
response = http_put("/indexes/#{@uid}/settings/facet-search", new_facet_search_setting)
|
725
|
+
|
726
|
+
Models::Task.new(response, task_endpoint)
|
657
727
|
end
|
658
728
|
|
659
729
|
def reset_facet_search_setting
|
660
|
-
http_delete("/indexes/#{@uid}/settings/facet-search")
|
730
|
+
response = http_delete("/indexes/#{@uid}/settings/facet-search")
|
731
|
+
|
732
|
+
Models::Task.new(response, task_endpoint)
|
661
733
|
end
|
662
734
|
|
663
735
|
### SETTINGS - PREFIX SEARCH
|
@@ -667,11 +739,15 @@ module Meilisearch
|
|
667
739
|
end
|
668
740
|
|
669
741
|
def update_prefix_search(new_prefix_search_setting)
|
670
|
-
http_put("/indexes/#{@uid}/settings/prefix-search", new_prefix_search_setting)
|
742
|
+
response = http_put("/indexes/#{@uid}/settings/prefix-search", new_prefix_search_setting)
|
743
|
+
|
744
|
+
Models::Task.new(response, task_endpoint)
|
671
745
|
end
|
672
746
|
|
673
747
|
def reset_prefix_search
|
674
|
-
http_delete("/indexes/#{@uid}/settings/prefix-search")
|
748
|
+
response = http_delete("/indexes/#{@uid}/settings/prefix-search")
|
749
|
+
|
750
|
+
Models::Task.new(response, task_endpoint)
|
675
751
|
end
|
676
752
|
|
677
753
|
### SETTINGS - EMBEDDERS
|
@@ -683,11 +759,15 @@ module Meilisearch
|
|
683
759
|
def update_embedders(new_embedders)
|
684
760
|
new_embedders = Utils.transform_attributes(new_embedders)
|
685
761
|
|
686
|
-
http_patch("/indexes/#{@uid}/settings/embedders", new_embedders)
|
762
|
+
response = http_patch("/indexes/#{@uid}/settings/embedders", new_embedders)
|
763
|
+
|
764
|
+
Models::Task.new(response, task_endpoint)
|
687
765
|
end
|
688
766
|
|
689
767
|
def reset_embedders
|
690
|
-
http_delete("/indexes/#{@uid}/settings/embedders")
|
768
|
+
response = http_delete("/indexes/#{@uid}/settings/embedders")
|
769
|
+
|
770
|
+
Models::Task.new(response, task_endpoint)
|
691
771
|
end
|
692
772
|
end
|
693
773
|
end
|
@@ -5,6 +5,21 @@ require 'forwardable'
|
|
5
5
|
module Meilisearch
|
6
6
|
module Models
|
7
7
|
class Task
|
8
|
+
DEFAULT_TIMEOUT_MS = 5000
|
9
|
+
DEFAULT_INTERVAL_MS = 50
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_writer :default_timeout_ms, :default_interval_ms
|
13
|
+
|
14
|
+
def default_timeout_ms
|
15
|
+
@default_timeout_ms || DEFAULT_TIMEOUT_MS
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_interval_ms
|
19
|
+
@default_interval_ms || DEFAULT_INTERVAL_MS
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
8
23
|
extend Forwardable
|
9
24
|
|
10
25
|
# Maintain backwards compatibility with task hash return type
|
@@ -96,7 +111,10 @@ module Meilisearch
|
|
96
111
|
self
|
97
112
|
end
|
98
113
|
|
99
|
-
def await(
|
114
|
+
def await(
|
115
|
+
timeout_in_ms = self.class.default_timeout_ms,
|
116
|
+
interval_in_ms = self.class.default_interval_ms
|
117
|
+
)
|
100
118
|
refresh with: @task_endpoint.wait_for_task(uid, timeout_in_ms, interval_in_ms) unless finished?
|
101
119
|
|
102
120
|
self
|
@@ -2,10 +2,20 @@
|
|
2
2
|
|
3
3
|
module Meilisearch
|
4
4
|
module MultiSearch
|
5
|
-
|
6
|
-
|
5
|
+
# Performs search on one or more indexes
|
6
|
+
#
|
7
|
+
# @param [Hash] federation_options
|
8
|
+
# - `limit`: number of results in the merged list
|
9
|
+
# - `offset`: number of results to skip in the merged list
|
10
|
+
def multi_search(data = nil, queries: [], federation: nil)
|
11
|
+
Utils.soft_deprecate('multi_search([])', 'multi_search(queries: [])') if data
|
7
12
|
|
8
|
-
|
13
|
+
queries += data if data
|
14
|
+
|
15
|
+
queries = Utils.transform_attributes(queries)
|
16
|
+
federation = Utils.transform_attributes(federation)
|
17
|
+
|
18
|
+
http_post '/multi-search', queries: queries, federation: federation
|
9
19
|
end
|
10
20
|
end
|
11
21
|
end
|
data/lib/meilisearch/task.rb
CHANGED
@@ -36,7 +36,19 @@ module Meilisearch
|
|
36
36
|
http_delete '/tasks', Utils.parse_query(options, ALLOWED_CANCELATION_PARAMS)
|
37
37
|
end
|
38
38
|
|
39
|
-
|
39
|
+
# Wait for a task with a busy loop.
|
40
|
+
#
|
41
|
+
# Not recommended, try to avoid interacting with Meilisearch synchronously.
|
42
|
+
# @param task_uid [String] uid of the task to wait on
|
43
|
+
# @param timeout_in_ms [Integer] the maximum amount of time to wait for a task
|
44
|
+
# in milliseconds
|
45
|
+
# @param interval_in_ms [Integer] how long to stay parked in the busy loop
|
46
|
+
# in milliseconds
|
47
|
+
def wait_for_task(
|
48
|
+
task_uid,
|
49
|
+
timeout_in_ms = Models::Task.default_timeout_ms,
|
50
|
+
interval_in_ms = Models::Task.default_interval_ms
|
51
|
+
)
|
40
52
|
Timeout.timeout(timeout_in_ms.to_f / 1000) do
|
41
53
|
loop do
|
42
54
|
task = task(task_uid)
|
data/lib/meilisearch/version.rb
CHANGED
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.
|
4
|
+
version: 0.32.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Meili
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0.
|
19
|
+
version: '0.22'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0.
|
26
|
+
version: '0.22'
|
27
27
|
description: An easy-to-use ruby client for Meilisearch API. See https://github.com/meilisearch/meilisearch
|
28
28
|
email: bonjour@meilisearch.com
|
29
29
|
executables: []
|