1- require_relative 'multi_search/result'
1+ require_relative 'multi_search/multi_search_result'
2+ require_relative 'multi_search/federated_search_result'
23
34module Meilisearch
45 module Rails
@@ -11,23 +12,59 @@ def multi_search(searches)
1112 normalize ( options , index_target )
1213 end
1314
14- MultiSearchResult . new ( searches , client . multi_search ( search_parameters ) )
15+ MultiSearchResult . new ( searches , client . multi_search ( queries : search_parameters ) )
16+ end
17+
18+ def federated_search ( queries :, federation : { } )
19+ if federation . nil?
20+ Meilisearch ::Rails . logger . warn (
21+ '[meilisearch-rails] In federated_search, `nil` is an invalid `:federation` option. To explicitly use defaults, pass `{}`.'
22+ )
23+
24+ federation = { }
25+ end
26+
27+ queries . map! { |item | [ nil , item ] } if queries . is_a? ( Array )
28+
29+ cleaned_queries = queries . filter_map do |( index_target , options ) |
30+ index_target = options . delete ( :index_uid ) || index_target || options [ :class_name ] &.constantize
31+
32+ strip_pagination_options ( options )
33+ normalize ( options , index_target )
34+ end
35+
36+ raw_results = client . multi_search ( queries : cleaned_queries , federation : federation )
37+
38+ FederatedSearchResult . new ( queries , raw_results )
1539 end
1640
1741 private
1842
1943 def normalize ( options , index_target )
44+ index_target = index_uid_from_target ( index_target )
45+
46+ return nil if index_target . nil?
47+
2048 options
2149 . except ( :class_name )
22- . merge! ( index_uid : index_uid_from_target ( index_target ) )
50+ . merge! ( index_uid : index_target )
2351 end
2452
2553 def index_uid_from_target ( index_target )
2654 case index_target
2755 when String , Symbol
2856 index_target
29- else
30- index_target . index . uid
57+ when Class
58+ if index_target . respond_to? ( :index )
59+ index_target . index . uid
60+ else
61+ Meilisearch ::Rails . logger . warn <<~MODEL_NOT_INDEXED
62+ [meilisearch-rails] This class was passed to a multi/federated search but it does not have an #index: #{ index_target }
63+ [meilisearch-rails] Are you sure it has a `meilisearch` block?
64+ MODEL_NOT_INDEXED
65+
66+ nil
67+ end
3168 end
3269 end
3370
@@ -43,6 +80,20 @@ def paginate(options)
4380 options [ :page ] ||= 1
4481 end
4582
83+ def strip_pagination_options ( options )
84+ pagination_options = %w[ page hitsPerPage hits_per_page limit offset ] . select do |key |
85+ options . delete ( key ) || options . delete ( key . to_sym )
86+ end
87+
88+ return if pagination_options . empty?
89+
90+ Meilisearch ::Rails . logger . warn <<~WRONG_PAGINATION
91+ [meilisearch-rails] Pagination options in federated search must apply to whole federation.
92+ [meilisearch-rails] These options have been removed: #{ pagination_options . join ( ', ' ) } .
93+ [meilisearch-rails] Please pass them after queries, in the `federation:` option.
94+ WRONG_PAGINATION
95+ end
96+
4697 def pagination_enabled?
4798 Meilisearch ::Rails . configuration [ :pagination_backend ]
4899 end
0 commit comments