Skip to content

Commit

Permalink
Implement faceting in search
Browse files Browse the repository at this point in the history
  • Loading branch information
curquiza committed Jun 4, 2020
1 parent 51c901e commit ad114ce
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 8 deletions.
4 changes: 2 additions & 2 deletions .rubocop_todo.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2020-06-04 09:43:58 +0200 using RuboCop version 0.85.0.
# on 2020-06-04 16:06:38 +0200 using RuboCop version 0.85.0.
# 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
Expand All @@ -15,7 +15,7 @@ Metrics/BlockLength:
# Offense count: 1
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 181
Max: 190

# Offense count: 2
# Configuration parameters: CountComments, ExcludedMethods.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,12 @@ To launch a specific folder or file:
$ bundle exec rspec spec/meilisearch/index/base_spec.rb
```

To launch a single test in a specific file:

```bash
$ bundle exec rspec spec/meilisearch/index/search_spec.rb -e 'does a basic search in index'
```

### Linter

Each PR should pass the linter to be accepted.
Expand Down
11 changes: 10 additions & 1 deletion lib/meilisearch/index.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,16 @@ def delete_all_documents
### SEARCH

def search(query, options = {})
http_get "/indexes/#{@uid}/search", { q: query }.merge(options)
parsed_options = options.transform_keys(&:to_sym).map do |k, v|
if [:facetFilters, :facetsDistribution].include?(k)
[k, v.inspect]
elsif v.is_a?(Array)
[k, v.join(',')]
else
[k, v]
end
end.to_h
http_get "/indexes/#{@uid}/search", { q: query }.merge(parsed_options)
end

### UPDATES
Expand Down
74 changes: 69 additions & 5 deletions spec/meilisearch/index/search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
RSpec.describe 'MeiliSearch::Index - Search' do
before(:all) do
documents = [
{ objectId: 123, title: 'Pride and Prejudice' },
{ objectId: 456, title: 'Le Petit Prince' },
{ objectId: 1, title: 'Alice In Wonderland' },
{ objectId: 1344, title: 'The Hobbit' },
{ objectId: 4, title: 'Harry Potter and the Half-Blood Prince' },
{ 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: 42, title: 'The Hitchhiker\'s Guide to the Galaxy' }
]
client = MeiliSearch::Client.new($URL, $MASTER_KEY)
Expand All @@ -21,18 +22,32 @@
@index.delete
end

let(:default_search_response_keys) do
[
'hits',
'offset',
'limit',
'nbHits',
'exhaustiveNbHits',
'processingTimeMs',
'query'
]
end

it 'does a basic search in index' do
response = @index.search('prince')
expect(response).to be_a(Hash)
expect(response).to have_key('hits')
expect(response['hits']).not_to be_empty
expect(response.keys).to contain_exactly(*default_search_response_keys)
expect(response['hits'].first).not_to have_key('_formatted')
end

it 'does a custom search with limit' do
response = @index.search('the', limit: 1)
expect(response).to be_a(Hash)
expect(response).to have_key('hits')
expect(response.keys).to contain_exactly(*default_search_response_keys)
expect(response['hits'].count).to eq(1)
expect(response['hits'].first).not_to have_key('_formatted')
end
Expand All @@ -41,7 +56,56 @@
response = @index.search('the', attributesToHighlight: '*')
expect(response).to be_a(Hash)
expect(response).to have_key('hits')
expect(response.keys).to contain_exactly(*default_search_response_keys)
expect(response['hits'].count).to eq(3)
expect(response['hits'].first).to have_key('_formatted')
end

it 'does a custom search with attributesToRetrieve as string' do
response = @index.search('the', attributesToRetrieve: 'title')
expect(response).to be_a(Hash)
expect(response).to have_key('hits')
expect(response.keys).to contain_exactly(*default_search_response_keys)
expect(response['hits'].count).to eq(3)
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')
end

it 'does a custom search with attributesToRetrieve as an array of string' do
response = @index.search('the', attributesToRetrieve: ['title', 'genre'])
expect(response).to be_a(Hash)
expect(response).to have_key('hits')
expect(response['hits'].count).to eq(3)
expect(response['hits'].first).to have_key('title')
expect(response.keys).to contain_exactly(*default_search_response_keys)
expect(response['hits'].first).not_to have_key('objectId')
expect(response['hits'].first).to have_key('genre')
end

it 'does a custom search with facetsDistribution' do
@index.update_attributes_for_faceting(['genre'])
sleep(0.1)
response = @index.search('prinec', facetsDistribution: ['genre'])
expect(response.keys).to contain_exactly(
*default_search_response_keys,
'facetsDistribution',
'exhaustiveFacetsCount'
)
expect(response['nbHits']).to eq(2)
expect(response['facetsDistribution'].keys).to contain_exactly('genre')
expect(response['facetsDistribution']['genre'].keys).to contain_exactly('romance', 'adventure', 'fantasy')
expect(response['facetsDistribution']['genre']['romance']).to eq(0)
expect(response['facetsDistribution']['genre']['adventure']).to eq(1)
expect(response['facetsDistribution']['genre']['fantasy']).to eq(1)
end

it 'does a custom search with facetFilters' do
@index.update_attributes_for_faceting(['genre'])
sleep(0.1)
response = @index.search('prinec', facetFilters: ['genre: fantasy'])
expect(response.keys).to contain_exactly(*default_search_response_keys)
expect(response['nbHits']).to eq(1)
expect(response['hits'][0]['objectId']).to eq(4)
end
end

0 comments on commit ad114ce

Please sign in to comment.