Skip to content

Commit b0248af

Browse files
committed
Implement multi-search pagination and refactor
1 parent ef6b019 commit b0248af

File tree

4 files changed

+74
-29
lines changed

4 files changed

+74
-29
lines changed

lib/meilisearch/rails/multi_search.rb

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,45 @@ module Rails
55
class << self
66
def multi_search(searches)
77
search_parameters = searches.map do |(index_target, options)|
8-
index_uid = case index_target
9-
when String, Symbol
10-
index_target
11-
else
12-
index_target.index.uid
13-
end
14-
15-
options.except(:class_name).merge(index_uid: index_uid)
8+
paginate(options) if pagination_enabled?
9+
normalize(options, index_target)
1610
end
1711

18-
raw_results = client.multi_search(search_parameters)['results']
12+
MultiSearchResult.new(searches, client.multi_search(search_parameters))
13+
end
14+
15+
16+
private
17+
18+
def normalize(options, index_target)
19+
options
20+
.except(:class_name)
21+
.merge!(index_uid: index_uid_from_target(index_target))
22+
end
23+
24+
def index_uid_from_target(index_target)
25+
case index_target
26+
when String, Symbol
27+
index_target
28+
else
29+
index_target.index.uid
30+
end
31+
end
32+
33+
def paginate(options)
34+
%w[page hitsPerPage hits_per_page].each do |key|
35+
# Deletes hitsPerPage to avoid passing along a meilisearch-ruby warning/exception
36+
value = options.delete(key) || options.delete(key.to_sym)
37+
options[key.underscore.to_sym] = value.to_i if value
38+
end
39+
40+
# It is required to activate the finite pagination in Meilisearch v0.30 (or newer),
41+
# to have at least `hits_per_page` defined or `page` in the search request.
42+
options[:page] ||= 1
43+
end
1944

20-
MultiSearchResult.new(searches, raw_results)
45+
def pagination_enabled?
46+
MeiliSearch::Rails.configuration[:pagination_backend]
2147
end
2248
end
2349
end

lib/meilisearch/rails/multi_search/result.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ def initialize(searches, raw_results)
77
@results = {}
88
@metadata = {}
99

10-
searches.zip(raw_results).each do |(index_target, search_options), result|
10+
searches.zip(raw_results['results']).each do |(index_target, search_options), result|
1111
index_target = search_options[:class_name].constantize if search_options[:class_name]
1212

1313
@results[index_target] = case index_target

spec/multi_search/result_spec.rb

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,22 @@
22

33
describe MeiliSearch::Rails::MultiSearchResult do # rubocop:todo RSpec/FilePath
44
let(:raw_results) do
5-
[
6-
{ 'indexUid' => 'books_index',
7-
'hits' => [{ 'name' => 'Steve Jobs', 'id' => '3', 'author' => 'Walter Isaacson', 'premium' => nil, 'released' => nil, 'genre' => nil }],
8-
'query' => 'Steve', 'processingTimeMs' => 0, 'limit' => 20, 'offset' => 0, 'estimatedTotalHits' => 1 },
9-
{ 'indexUid' => 'products_index',
10-
'hits' => [{ 'id' => '4', 'href' => 'ebay', 'name' => 'palm pixi plus' }],
11-
'query' => 'palm', 'processingTimeMs' => 0, 'limit' => 1, 'offset' => 0, 'estimatedTotalHits' => 2 },
12-
{ 'indexUid' => 'color_index',
13-
'hits' => [
14-
{ 'name' => 'black', 'id' => '5', 'short_name' => 'bla', 'hex' => 0 },
15-
{ 'name' => 'blue', 'id' => '4', 'short_name' => 'blu', 'hex' => 255 }
16-
],
17-
'query' => 'bl', 'processingTimeMs' => 0, 'limit' => 20, 'offset' => 0, 'estimatedTotalHits' => 2 }
18-
]
5+
{
6+
'results' => [
7+
{ 'indexUid' => 'books_index',
8+
'hits' => [{ 'name' => 'Steve Jobs', 'id' => '3', 'author' => 'Walter Isaacson', 'premium' => nil, 'released' => nil, 'genre' => nil }],
9+
'query' => 'Steve', 'processingTimeMs' => 0, 'limit' => 20, 'offset' => 0, 'estimatedTotalHits' => 1 },
10+
{ 'indexUid' => 'products_index',
11+
'hits' => [{ 'id' => '4', 'href' => 'ebay', 'name' => 'palm pixi plus' }],
12+
'query' => 'palm', 'processingTimeMs' => 0, 'limit' => 1, 'offset' => 0, 'estimatedTotalHits' => 2 },
13+
{ 'indexUid' => 'color_index',
14+
'hits' => [
15+
{ 'name' => 'black', 'id' => '5', 'short_name' => 'bla', 'hex' => 0 },
16+
{ 'name' => 'blue', 'id' => '4', 'short_name' => 'blu', 'hex' => 255 }
17+
],
18+
'query' => 'bl', 'processingTimeMs' => 0, 'limit' => 20, 'offset' => 0, 'estimatedTotalHits' => 2 }
19+
]
20+
}
1921
end
2022

2123
it 'is enumerable' do

spec/multi_search_spec.rb

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,11 @@
44
def reset_indexes
55
[Book, Color, Product].each do |klass|
66
klass.delete_all
7-
klass.index.delete_all_documents
7+
klass.clear_index!
88
end
99
end
1010

11-
before(:all) { reset_indexes } # rubocop:todo RSpec/BeforeAfterAll
12-
13-
after { reset_indexes }
11+
before { reset_indexes }
1412

1513
let!(:palm_pixi_plus) { Product.create!(name: 'palm pixi plus', href: 'ebay', tags: ['terrible']) }
1614
let!(:steve_jobs) { Book.create! name: 'Steve Jobs', author: 'Walter Isaacson' }
@@ -96,4 +94,23 @@ def reset_indexes
9694
)
9795
end
9896
end
97+
98+
context 'with pagination' do
99+
it 'it properly paginates each search' do
100+
MeiliSearch::Rails.configuration[:pagination_backend] = :kaminari
101+
102+
results = MeiliSearch::Rails.multi_search(
103+
Book => { q: 'Steve' },
104+
Product => { q: 'palm', page: 1, hits_per_page: 1 },
105+
Color.index.uid => { q: 'bl', page: 1, 'hitsPerPage' => '1' }
106+
)
107+
108+
expect(results).to contain_exactly(
109+
steve_jobs, palm_pixi_plus,
110+
a_hash_including('name' => 'black', 'short_name' => 'bla')
111+
)
112+
113+
MeiliSearch::Rails.configuration[:pagination_backend] = nil
114+
end
115+
end
99116
end

0 commit comments

Comments
 (0)