Skip to content

Commit

Permalink
Merge #496
Browse files Browse the repository at this point in the history
496: Implement facet_search r=brunoocasali a=ellnix

# Pull Request

## Related issue
Fixes #462

## PR checklist
Please check if your PR fulfills the following requirements:
- [X] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
- [X] Have you read the contributing guidelines?
- [X] Have you made sure that the title is accurate and descriptive of the changes?


Co-authored-by: ellnix <103502144+ellnix@users.noreply.github.com>
  • Loading branch information
meili-bors[bot] and ellnix authored Oct 16, 2023
2 parents fb6bbc0 + 5e31f7c commit d2ffa58
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 3 deletions.
4 changes: 4 additions & 0 deletions .code-samples.meilisearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -603,12 +603,16 @@ multi_search_1: |-
{ index_uid: 'movies', q: 'nemo', limit: 5 }
{ index_uid: 'movie_ratings', q: 'us' }
])
facet_search_1: |-
client.index('books').facet_search('genres', 'fiction', filter: 'rating > 3')
facet_search_2: |-
client.index('books').update_faceting(
sort_facet_values_by: {
genres: 'count'
}
)
facet_search_3: |-
client.index('books').facet_search('genres', 'c')
get_dictionary_1: |-
client.index('books').dictionary
update_dictionary_1: |-
Expand Down
6 changes: 3 additions & 3 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2023-10-10 14:01:22 UTC using RuboCop version 1.50.2.
# on 2023-10-11 10:43:57 UTC using RuboCop version 1.50.2.
# 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
# versions of RuboCop, may require this file to be generated again.

# Offense count: 52
# Offense count: 55
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
# AllowedMethods: refine
Metrics/BlockLength:
Expand All @@ -15,7 +15,7 @@ Metrics/BlockLength:
# Offense count: 2
# Configuration parameters: CountComments, CountAsOne.
Metrics/ClassLength:
Max: 358
Max: 363

# Offense count: 1
# Configuration parameters: Max, CountKeywordArgs.
Expand Down
9 changes: 9 additions & 0 deletions lib/meilisearch/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,15 @@ def search(query, options = {})
response
end

### FACET SEARCH

def facet_search(name, query = '', **options)
options.merge!(facet_name: name, facet_query: query)
options = Utils.transform_attributes(options)

http_post("/indexes/#{@uid}/facet-search", options)
end

### TASKS

def task_endpoint
Expand Down
111 changes: 111 additions & 0 deletions spec/meilisearch/index/search/facet_search_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# frozen_string_literal: true

RSpec.describe 'MeiliSearch::Index - Facet search' do
include_context 'search books with author, genre, year'

before do
response = index.update_filterable_attributes(['genre', 'year', 'author'])
index.wait_for_task(response['taskUid'])
end

it 'requires facet name parameter' do
expect { index.facet_search }.to raise_error ArgumentError
end

context 'without query parameter' do
let(:results) { index.facet_search 'genre' }

it 'returns all genres' do
expect(results).to include(
'facetHits' => a_collection_including(
a_hash_including('value' => 'fantasy'),
a_hash_including('value' => 'adventure'),
a_hash_including('value' => 'romance')
)
)
end

it 'returns all genre counts' do
expect(results).to include(
'facetHits' => a_collection_including(
a_hash_including('count' => 3),
a_hash_including('count' => 3),
a_hash_including('count' => 2)
)
)
end

it 'filters correctly' do
results = index.facet_search 'genre', filter: 'year < 1940'

expect(results['facetHits']).to contain_exactly(
{
'value' => 'adventure',
'count' => 2
},
{
'value' => 'romance',
'count' => 2
}
)
end
end

context 'with facet_query argument' do
let(:results) { index.facet_search 'genre', 'fan' }

it 'returns only matching genres' do
expect(results).to include(
'facetHits' => a_collection_containing_exactly(
'value' => 'fantasy',
'count' => 3
)
)
end

it 'filters correctly' do
results = index.facet_search 'genre', 'fantasy', filter: 'year < 2006'

expect(results['facetHits']).to contain_exactly(
'value' => 'fantasy',
'count' => 2
)
end
end

context 'with q parameter' do
it 'applies matching_strategy "all"' do
results = index.facet_search 'author', 'J. K. Rowling', q: 'Potter Stories', matching_strategy: 'all'

expect(results['facetHits']).to be_empty
end

it 'applies matching_strategy "last"' do
results = index.facet_search 'author', 'J. K. Rowling', q: 'Potter Stories', matching_strategy: 'last'

expect(results).to include(
'facetHits' => a_collection_containing_exactly(
'value' => 'J. K. Rowling',
'count' => 2
)
)
end

it 'applies filter parameter' do
results = index.facet_search 'author', 'J. K. Rowling', q: 'Potter', filter: 'year < 2007'

expect(results).to include(
'facetHits' => a_collection_containing_exactly(
'value' => 'J. K. Rowling',
'count' => 1
)
)
end

it 'applies attributes_to_search_on parameter' do
results = index.facet_search 'author', 'J. K. Rowling', q: 'Potter', attributes_to_search_on: ['year']

expect(results['facetHits']).to be_empty
end
end
end

0 comments on commit d2ffa58

Please sign in to comment.