Skip to content

Commit d1a776b

Browse files
meili-bors[bot]meili-botbrunoocasali
authored
Merge #437
437: Changes related to the next Meilisearch release (v1.2.0) r=brunoocasali a=meili-bot Related to this issue: meilisearch/integration-guides#261 This PR: - gathers the changes related to the next Meilisearch release (v1.2.0) so that this package is ready when the official release is out. - should pass the tests against the [latest pre-release of Meilisearch](https://github.com/meilisearch/meilisearch/releases). - might eventually contain test failures until the Meilisearch v1.2.0 is out. ⚠️ This PR should NOT be merged until the next release of Meilisearch (v1.2.0) is out. _This PR is auto-generated for the [pre-release week](https://github.com/meilisearch/integration-guides/blob/main/resources/pre-release-week.md) purpose._ Co-authored-by: meili-bot <[email protected]> Co-authored-by: Bruno Casali <[email protected]>
2 parents 73ff674 + d11ce6a commit d1a776b

File tree

6 files changed

+143
-28
lines changed

6 files changed

+143
-28
lines changed

.rubocop_todo.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2023-03-30 12:31:09 UTC using RuboCop version 1.48.1.
3+
# on 2023-05-20 02:24:12 UTC using RuboCop version 1.50.2.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
@@ -14,7 +14,7 @@ Gemspec/RequireMFA:
1414
Exclude:
1515
- 'meilisearch.gemspec'
1616

17-
# Offense count: 45
17+
# Offense count: 47
1818
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
1919
# AllowedMethods: refine
2020
Metrics/BlockLength:
@@ -23,7 +23,7 @@ Metrics/BlockLength:
2323
# Offense count: 2
2424
# Configuration parameters: CountComments, CountAsOne.
2525
Metrics/ClassLength:
26-
Max: 318
26+
Max: 327
2727

2828
# Offense count: 1
2929
# Configuration parameters: Max, CountKeywordArgs.

lib/meilisearch/index.rb

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,24 @@ def document(document_id, fields: nil)
6363
alias get_document document
6464
alias get_one_document document
6565

66+
# Public: Retrieve documents from a index.
67+
#
68+
# options - The hash options used to refine the selection (default: {}):
69+
# :limit - Number of documents to return (optional).
70+
# :offset - Number of documents to skip (optional).
71+
# :fields - Array of document attributes to show (optional).
72+
# :filter - Filter queries by an attribute's value.
73+
# Available ONLY with Meilisearch v1.2 and newer (optional).
74+
#
75+
# Returns the documents results object.
6676
def documents(options = {})
67-
http_get "/indexes/#{@uid}/documents", Utils.parse_query(options, [:limit, :offset, :fields])
77+
Utils.version_error_handler(__method__) do
78+
if options.key?(:filter)
79+
http_post "/indexes/#{@uid}/documents/fetch", Utils.filter(options, [:limit, :offset, :fields, :filter])
80+
else
81+
http_get "/indexes/#{@uid}/documents", Utils.parse_query(options, [:limit, :offset, :fields])
82+
end
83+
end
6884
end
6985
alias get_documents documents
7086

@@ -153,11 +169,24 @@ def update_documents_in_batches!(documents, batch_size = 1000, primary_key = nil
153169
responses
154170
end
155171

156-
def delete_documents(documents_ids)
157-
if documents_ids.is_a?(Array)
158-
http_post "/indexes/#{@uid}/documents/delete-batch", documents_ids
159-
else
160-
delete_document(documents_ids)
172+
# Public: Delete documents from an index
173+
#
174+
# options: A Hash or an Array containing documents_ids or a hash with filter:.
175+
# filter: - A hash containing a filter that should match documents.
176+
# Available ONLY with Meilisearch v1.2 and newer (optional)
177+
#
178+
# Returns a Task object.
179+
def delete_documents(options = {})
180+
Utils.version_error_handler(__method__) do
181+
if options.is_a?(Hash) && options.key?(:filter)
182+
http_post "/indexes/#{@uid}/documents/delete", options
183+
else
184+
# backwards compatibility:
185+
# expect to be a array or/number/string to send alongside as documents_ids.
186+
options = [options] unless options.is_a?(Array)
187+
188+
http_post "/indexes/#{@uid}/documents/delete-batch", options
189+
end
161190
end
162191
end
163192
alias delete_multiple_documents delete_documents

lib/meilisearch/utils.rb

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ def self.parse(body)
2323
end
2424
end
2525

26+
def self.filter(original_options, allowed_params = [])
27+
original_options.transform_keys(&:to_sym).slice(*allowed_params)
28+
end
29+
2630
def self.parse_query(original_options, allowed_params = [])
27-
only_allowed_params = original_options.transform_keys(&:to_sym).slice(*allowed_params)
31+
only_allowed_params = filter(original_options, allowed_params)
2832

2933
Utils.transform_attributes(only_allowed_params).then do |body|
3034
body.transform_values do |v|
@@ -33,6 +37,21 @@ def self.parse_query(original_options, allowed_params = [])
3337
end
3438
end
3539

36-
private_class_method :parse
40+
def self.message_builder(current_message, method_name)
41+
"#{current_message}\nHint: It might not be working because maybe you're not up " \
42+
"to date with the Meilisearch version that `#{method_name}` call requires."
43+
end
44+
45+
def self.version_error_handler(method_name)
46+
yield if block_given?
47+
rescue MeiliSearch::ApiError => e
48+
message = message_builder(e.http_message, method_name)
49+
50+
raise MeiliSearch::ApiError.new(e.http_code, message, e.http_body)
51+
rescue StandardError => e
52+
raise e.class, message_builder(e.message, method_name)
53+
end
54+
55+
private_class_method :parse, :message_builder
3756
end
3857
end

spec/meilisearch/index/documents_spec.rb

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,28 @@
3737
end
3838

3939
it 'adds JSON documents (as a array of documents)' do
40-
documents = <<JSON
41-
[
42-
{ "objectRef": 123, "title": "Pride and Prejudice", "comment": "A great book" },
43-
{ "objectRef": 456, "title": "Le Petit Prince", "comment": "A french book" },
44-
{ "objectRef": 1, "title": "Alice In Wonderland", "comment": "A weird book" },
45-
{ "objectRef": 1344, "title": "The Hobbit", "comment": "An awesome book" },
46-
{ "objectRef": 4, "title": "Harry Potter and the Half-Blood Prince", "comment": "The best book" }
47-
]
48-
JSON
40+
documents = <<~JSON
41+
[
42+
{ "objectRef": 123, "title": "Pride and Prejudice", "comment": "A great book" },
43+
{ "objectRef": 456, "title": "Le Petit Prince", "comment": "A french book" },
44+
{ "objectRef": 1, "title": "Alice In Wonderland", "comment": "A weird book" },
45+
{ "objectRef": 1344, "title": "The Hobbit", "comment": "An awesome book" },
46+
{ "objectRef": 4, "title": "Harry Potter and the Half-Blood Prince", "comment": "The best book" }
47+
]
48+
JSON
4949
response = index.add_documents_json(documents, 'objectRef')
5050

5151
index.wait_for_task(response['taskUid'])
5252
expect(index.documents['results'].count).to eq(5)
5353
end
5454

5555
it 'adds NDJSON documents (as a array of documents)' do
56-
documents = <<NDJSON
57-
{ "objectRef": 123, "title": "Pride and Prejudice", "comment": "A great book" }
58-
{ "objectRef": 456, "title": "Le Petit Prince", "comment": "A french book" }
59-
{ "objectRef": 1, "title": "Alice In Wonderland", "comment": "A weird book" }
60-
{ "objectRef": 4, "title": "Harry Potter and the Half-Blood Prince", "comment": "The best book" }
61-
NDJSON
56+
documents = <<~NDJSON
57+
{ "objectRef": 123, "title": "Pride and Prejudice", "comment": "A great book" }
58+
{ "objectRef": 456, "title": "Le Petit Prince", "comment": "A french book" }
59+
{ "objectRef": 1, "title": "Alice In Wonderland", "comment": "A weird book" }
60+
{ "objectRef": 4, "title": "Harry Potter and the Half-Blood Prince", "comment": "The best book" }
61+
NDJSON
6262
response = index.add_documents_ndjson(documents, 'objectRef')
6363

6464
index.wait_for_task(response['taskUid'])
@@ -196,7 +196,12 @@
196196
end
197197

198198
describe 'accessing documents' do
199-
before { index.add_documents!(documents) }
199+
before do
200+
index.add_documents(documents)
201+
202+
task = index.update_filterable_attributes(['title', 'objectId'])
203+
client.wait_for_task(task['taskUid'])
204+
end
200205

201206
it 'gets one document from its primary-key' do
202207
task = index.document(123)
@@ -228,6 +233,25 @@
228233
expect(docs).to be_a(Array)
229234
expect(docs.first.keys).to eq(['title'])
230235
end
236+
237+
it 'retrieves documents by filters' do
238+
docs = index.documents(filter: 'objectId > 400')['results']
239+
240+
expect(docs).to be_a(Array)
241+
expect(docs.first).to eq({
242+
'objectId' => 456,
243+
'title' => 'Le Petit Prince',
244+
'comment' => 'A french book'
245+
})
246+
end
247+
248+
it 'retrieves documents by filters & other parameters' do
249+
docs = index.documents(fields: ['title'], filter: 'objectId > 100')['results']
250+
251+
expect(docs).to be_a(Array)
252+
expect(docs.size).to eq(3)
253+
expect(docs.first.keys).to eq(['title'])
254+
end
231255
end
232256

233257
describe 'updating documents' do
@@ -390,6 +414,23 @@
390414
expect { index.document(id) }.to raise_document_not_found_meilisearch_api_error
391415
end
392416

417+
it 'deletes documents based on filter from index (with delete route)' do
418+
expect do
419+
index.update_filterable_attributes(['objectId'])
420+
task = index.delete_documents(filter: ['objectId > 0'])
421+
422+
client.wait_for_task(task['taskUid'])
423+
end.to(change { index.documents['results'].size }.by(-documents.size))
424+
end
425+
426+
it 'ignores filter even when documents_ids is empty (with delete-batch route)' do
427+
expect do
428+
task = index.delete_documents(filter: ['objectId > 0'])
429+
430+
client.wait_for_task(task['taskUid'])
431+
end.to(change { index.documents['results'].size }.by(0))
432+
end
433+
393434
it 'deletes one document synchronously from index (with delete-batch route)' do
394435
id = 2
395436
expect do

spec/meilisearch/index/search/multi_params_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
expect(response['hits'].first).not_to have_key('objectId')
6060
expect(response['hits'].first).not_to have_key('genre')
6161
expect(response['hits'].first).to have_key('title')
62-
expect(response['hits'].first['_formatted']['title']).to eq('Harry Potter and the Half-Blood <em>Princ</em>e')
62+
expect(response['hits'].first['_formatted']['title']).to eq('Harry Potter and the Half-Blood <em>Prince</em>')
6363
end
6464

6565
it 'does a custom search with facets and limit' do

spec/meilisearch/utils_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,30 @@
4646
)
4747
end
4848
end
49+
50+
describe '.version_error_handler' do
51+
it 'spawns same error message' do
52+
expect do
53+
MeiliSearch::Utils.version_error_handler(:my_method) do
54+
raise MeiliSearch::ApiError.new(405, 'I came from Meili server', {})
55+
end
56+
end.to raise_error(MeiliSearch::ApiError, /I came from Meili server/)
57+
end
58+
59+
it 'spawns message with version hint' do
60+
expect do
61+
MeiliSearch::Utils.version_error_handler(:my_method) do
62+
raise MeiliSearch::ApiError.new(405, 'I came from Meili server', {})
63+
end
64+
end.to raise_error(MeiliSearch::ApiError, /that `my_method` call requires/)
65+
end
66+
67+
it 'adds hints to all error types' do
68+
expect do
69+
MeiliSearch::Utils.version_error_handler(:my_method) do
70+
raise MeiliSearch::CommunicationError, 'I am an error'
71+
end
72+
end.to raise_error(MeiliSearch::CommunicationError, /that `my_method` call requires/)
73+
end
74+
end
4975
end

0 commit comments

Comments
 (0)