diff --git a/.code-samples.meilisearch.yaml b/.code-samples.meilisearch.yaml
index efcf98a4..87438e7b 100644
--- a/.code-samples.meilisearch.yaml
+++ b/.code-samples.meilisearch.yaml
@@ -655,3 +655,21 @@ reset_search_cutoff_1: |-
client.index('movies').reset_search_cutoff_ms
get_similar_post_1: |-
client.index('INDEX_NAME').search_similar_documents('TARGET_DOCUMENT_ID')
+search_parameter_reference_ranking_score_threshold_1: |-
+ client.index('INDEX_NAME').search('badman', {
+ rankingScoreThreshold: 0.2
+ })
+search_parameter_reference_distinct_1: |-
+ client.index('INDEX_NAME').search('QUERY TERMS', {
+ distinct: 'ATTRIBUTE_A'
+ })
+distinct_attribute_guide_filterable_1: |-
+ client.index('products').update_filterable_attributes([
+ 'product_id',
+ 'sku',
+ 'url'
+ ])
+distinct_attribute_guide_distinct_parameter_1: |-
+ client.index('products').search('white shirt', {
+ distinct: 'sku'
+ })
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 1e4b6a07..dd4fa883 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -19,7 +19,7 @@ jobs:
matrix:
ruby-version: ['3.1', '3.2', '3.3']
name: integration-tests (ruby ${{ matrix.ruby-version }})
- runs-on: ubuntu-22.04
+ runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Ruby ${{ matrix.ruby-version }}
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 5a5b9cff..7e33d7b1 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2024-06-01 14:58:01 UTC using RuboCop version 1.63.5.
+# on 2024-09-10 01:25:16 UTC using RuboCop version 1.65.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
diff --git a/Gemfile b/Gemfile
index 5d069e5e..2487b1d9 100644
--- a/Gemfile
+++ b/Gemfile
@@ -18,5 +18,5 @@ group :development, :test do
end
group :development do
- gem 'rubocop', '~> 1.64.1', require: false
+ gem 'rubocop', '~> 1.66.0', require: false
end
diff --git a/docker-compose.yml b/docker-compose.yml
index 091047f5..1c94bad7 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -3,7 +3,7 @@ volumes:
services:
package:
- image: ruby:3.0
+ image: ruby:3.3
tty: true
stdin_open: true
working_dir: /home/package
diff --git a/lib/meilisearch.rb b/lib/meilisearch.rb
index f7a58e49..e72bb54a 100644
--- a/lib/meilisearch.rb
+++ b/lib/meilisearch.rb
@@ -1,5 +1,7 @@
# frozen_string_literal: true
+require 'json'
+
require 'meilisearch/version'
require 'meilisearch/utils'
require 'meilisearch/models/task'
diff --git a/lib/meilisearch/error.rb b/lib/meilisearch/error.rb
index 01420f09..02a1f40e 100644
--- a/lib/meilisearch/error.rb
+++ b/lib/meilisearch/error.rb
@@ -70,6 +70,15 @@ def initialize(message = nil)
end
end
+ class InvalidDocumentId < Error
+ attr_reader :message
+
+ def initialize(message = nil)
+ @message = "The document id is invalid. #{message}"
+ super(@message)
+ end
+ end
+
module TenantToken
class ExpireOrInvalidSignature < MeiliSearch::Error; end
class InvalidApiKey < MeiliSearch::Error; end
diff --git a/lib/meilisearch/index.rb b/lib/meilisearch/index.rb
index 6c6a7643..96b45bea 100644
--- a/lib/meilisearch/index.rb
+++ b/lib/meilisearch/index.rb
@@ -220,6 +220,10 @@ def delete_documents!(documents_ids)
alias delete_multiple_documents! delete_documents!
def delete_document(document_id)
+ if document_id.nil? || document_id.to_s.empty?
+ raise MeiliSearch::InvalidDocumentId, 'document_id cannot be empty or nil'
+ end
+
encode_document = URI.encode_www_form_component(document_id)
response = http_delete "/indexes/#{@uid}/documents/#{encode_document}"
diff --git a/lib/meilisearch/version.rb b/lib/meilisearch/version.rb
index 7291b5c4..af2165b0 100644
--- a/lib/meilisearch/version.rb
+++ b/lib/meilisearch/version.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
module MeiliSearch
- VERSION = '0.28.0'
+ VERSION = '0.28.3'
def self.qualified_version
"Meilisearch Ruby (v#{VERSION})"
diff --git a/meilisearch.gemspec b/meilisearch.gemspec
index 3fa62de9..6fb3e896 100644
--- a/meilisearch.gemspec
+++ b/meilisearch.gemspec
@@ -15,6 +15,6 @@ Gem::Specification.new do |s|
s.files = Dir['{lib}/**/*', 'LICENSE', 'README.md']
s.required_ruby_version = '>= 3.0.0'
- s.add_dependency 'httparty', '~> 0.17.1'
+ s.add_dependency 'httparty', '~> 0.17'
s.metadata['rubygems_mfa_required'] = 'true'
end
diff --git a/spec/meilisearch/client/errors_spec.rb b/spec/meilisearch/client/errors_spec.rb
index 10843cf4..1c010c68 100644
--- a/spec/meilisearch/client/errors_spec.rb
+++ b/spec/meilisearch/client/errors_spec.rb
@@ -33,4 +33,12 @@
end.to raise_error(MeiliSearch::CommunicationError)
end
end
+
+ context 'when document id is invalid' do
+ it 'raises MeiliSearch::InvalidDocumentId' do
+ expect do
+ client.index('movies').delete_document(nil)
+ end.to raise_error(MeiliSearch::InvalidDocumentId)
+ end
+ end
end
diff --git a/spec/meilisearch/index/documents_spec.rb b/spec/meilisearch/index/documents_spec.rb
index b1984f78..d54d5a5f 100644
--- a/spec/meilisearch/index/documents_spec.rb
+++ b/spec/meilisearch/index/documents_spec.rb
@@ -393,6 +393,10 @@
describe '#delete_document' do
before { index.add_documents(documents).await }
+ it 'if the document id is nil, it raises an error' do
+ expect { index.delete_document(nil) }.to raise_error(MeiliSearch::InvalidDocumentId)
+ end
+
it 'deletes one document from index' do
id = 456
index.delete_document(id).await
diff --git a/spec/meilisearch/index/search/attributes_to_highlight_spec.rb b/spec/meilisearch/index/search/attributes_to_highlight_spec.rb
index 498f7cf6..d9df5b0a 100644
--- a/spec/meilisearch/index/search/attributes_to_highlight_spec.rb
+++ b/spec/meilisearch/index/search/attributes_to_highlight_spec.rb
@@ -7,7 +7,7 @@
response = index.search('the', attributes_to_highlight: ['title'])
expect(response).to be_a(Hash)
expect(response.keys).to contain_exactly(*DEFAULT_SEARCH_RESPONSE_KEYS)
- expect(response['hits'].count).to eq(3)
+ expect(response['hits'].count).to eq(4)
expect(response['hits'].first).to have_key('_formatted')
expect(response['hits'].first['_formatted']['title']).to eq('The Hobbit')
end
@@ -16,7 +16,7 @@
response = index.search('', attributes_to_highlight: ['*'])
expect(response).to be_a(Hash)
expect(response.keys).to contain_exactly(*DEFAULT_SEARCH_RESPONSE_KEYS)
- expect(response['hits'].count).to eq(7)
+ expect(response['hits'].count).to eq(8)
expect(response['hits'].first).to have_key('_formatted')
end
diff --git a/spec/meilisearch/index/search/attributes_to_retrieve_spec.rb b/spec/meilisearch/index/search/attributes_to_retrieve_spec.rb
index ee7d6422..d82e455b 100644
--- a/spec/meilisearch/index/search/attributes_to_retrieve_spec.rb
+++ b/spec/meilisearch/index/search/attributes_to_retrieve_spec.rb
@@ -7,7 +7,7 @@
response = index.search('the', attributes_to_retrieve: ['title'])
expect(response).to be_a(Hash)
expect(response.keys).to contain_exactly(*DEFAULT_SEARCH_RESPONSE_KEYS)
- expect(response['hits'].count).to eq(3)
+ expect(response['hits'].count).to eq(4)
expect(response['hits'].first).to have_key('title')
expect(response['hits'].first).not_to have_key('objectId')
expect(response['hits'].first).not_to have_key('genre')
@@ -17,7 +17,7 @@
response = index.search('the', attributes_to_retrieve: ['title', 'genre'])
expect(response).to be_a(Hash)
expect(response.keys).to contain_exactly(*DEFAULT_SEARCH_RESPONSE_KEYS)
- expect(response['hits'].count).to eq(3)
+ expect(response['hits'].count).to eq(4)
expect(response['hits'].first).to have_key('title')
expect(response['hits'].first).not_to have_key('objectId')
expect(response['hits'].first).to have_key('genre')
@@ -27,7 +27,7 @@
response = index.search('the', attributes_to_retrieve: ['*'])
expect(response).to be_a(Hash)
expect(response.keys).to contain_exactly(*DEFAULT_SEARCH_RESPONSE_KEYS)
- expect(response['hits'].count).to eq(3)
+ expect(response['hits'].count).to eq(4)
expect(response['hits'].first).to have_key('objectId')
expect(response['hits'].first).to have_key('title')
expect(response['hits'].first).to have_key('genre')
diff --git a/spec/meilisearch/index/search/distinct_spec.rb b/spec/meilisearch/index/search/distinct_spec.rb
new file mode 100644
index 00000000..d6d0dabd
--- /dev/null
+++ b/spec/meilisearch/index/search/distinct_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+RSpec.describe 'MeiliSearch::Index - Distinct search' do
+ include_context 'search books with genre'
+
+ before do
+ index.update_filterable_attributes(['genre']).await
+ end
+
+ it 'does a search without distinct' do
+ response = index.search('harry potter')
+ expect(response['hits'].count).to eq(2)
+ end
+
+ it 'does a custom search with distinct' do
+ response = index.search('harry potter', { distinct: 'genre' })
+ expect(response['hits'].count).to eq(1)
+ end
+end
diff --git a/spec/meilisearch/index/search/q_spec.rb b/spec/meilisearch/index/search/q_spec.rb
index d018e8be..7b17cbc1 100644
--- a/spec/meilisearch/index/search/q_spec.rb
+++ b/spec/meilisearch/index/search/q_spec.rb
@@ -64,7 +64,7 @@
response = index.search('coco "harry"')
expect(response).to be_a(Hash)
expect(response.keys).to contain_exactly(*DEFAULT_SEARCH_RESPONSE_KEYS)
- expect(response['hits'].count).to eq(1)
+ expect(response['hits'].count).to eq(2)
expect(response['hits'].first['objectId']).to eq(4)
expect(response['hits'].first).not_to have_key('_formatted')
end
diff --git a/spec/meilisearch/index/search/ranking_score_threshold_spec.rb b/spec/meilisearch/index/search/ranking_score_threshold_spec.rb
new file mode 100644
index 00000000..7d25e94f
--- /dev/null
+++ b/spec/meilisearch/index/search/ranking_score_threshold_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+RSpec.describe 'MeiliSearch::Index - Search with rankingScoreThreshold' do
+ include_context 'search books with genre'
+
+ it 'does a custom search with rankingScoreThreshold' do
+ response = index.search('harry potter and the prisoner of azkaban', { rankingScoreThreshold: 0.9 })
+ expect(response['hits'].count).to be(0)
+
+ response = index.search('harry potter and the', { rankingScoreThreshold: 0.3 })
+ expect(response['hits'].count).to be(2)
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 346e72a5..18170866 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -37,6 +37,7 @@
require 'meilisearch'
require 'byebug'
+require 'time'
# Globals for all tests
URL = format('http://%s:%s',
diff --git a/spec/support/books_contexts.rb b/spec/support/books_contexts.rb
index 83e40d2c..8d1a886e 100644
--- a/spec/support/books_contexts.rb
+++ b/spec/support/books_contexts.rb
@@ -4,12 +4,13 @@
let(:index) { client.index('books') }
let(:documents) do
[
- { objectId: 123, title: 'Pride and Prejudice', genre: 'romance' },
- { objectId: 456, title: 'Le Petit Prince', genre: 'adventure' },
- { objectId: 1, title: 'Alice In Wonderland', genre: 'adventure' },
- { objectId: 2, title: 'Le Rouge et le Noir', genre: 'romance' },
- { objectId: 1344, title: 'The Hobbit', genre: 'adventure' },
- { objectId: 4, title: 'Harry Potter and the Half-Blood Prince', genre: 'fantasy' },
+ { objectId: 123, title: 'Pride and Prejudice', genre: 'romance' },
+ { objectId: 456, title: 'Le Petit Prince', genre: 'adventure' },
+ { objectId: 1, title: 'Alice In Wonderland', genre: 'adventure' },
+ { objectId: 2, title: 'Le Rouge et le Noir', genre: 'romance' },
+ { objectId: 1344, title: 'The Hobbit', genre: 'adventure' },
+ { objectId: 4, title: 'Harry Potter and the Half-Blood Prince', genre: 'fantasy' },
+ { objectId: 7, title: 'Harry Potter and the Chamber of Secrets', genre: 'fantasy' },
{ objectId: 42, title: 'The Hitchhiker\'s Guide to the Galaxy' }
]
end