Paginieren Sie mehrere Modelle in Kaminari
-
26-10-2019 - |
Frage
Ich erstelle eine Suchseite, auf der eine anwendungsweite Suche nach Benutzern, Beiträgen und Kommentaren durchgeführt wird. Ich habe derzeit:
# POST /search
def index
query = params[:query]
@users = User.search(query).page(params[:page])
@posts = Post.search(query).page(params[:page])
@comments = Comment.search(query).page(params[:page])
respond_to do |format|
format.html
end
end
Ich versuche jedoch wirklich, etwas dort zu bekommen, wo alle Ergebnisse zusammengemischt werden und dann gepackt werden. Was sind einige der Strategien für so paginierte Suche? Vielen Dank!
Lösung
Bevor Sie über eine Lösung nachdenken, müssen Sie zuerst genau definieren, was das Endergebnis sein soll. Wenn Sie auf der Ergebnisseite einige von jedem Datensatztyp anzeigen möchten, können Sie den von Ihnen veröffentlichten Ansatz ändern und die drei pagierten Ergebnisse mithilfe miteinander kombinieren:
@results = @users + @posts + @comments
@results.sort! { |a, b| a.score(query) > b.score(query) }
Jedes Objekt muss über eine Instanzmethode "Score" verfügen, mit der sie basierend auf der Abfragepriorität sortieren können. Außerdem müssen Sie Ihre Ansicht ändern, um das korrekte Rendering jedes Elements zu verarbeiten und sicherzustellen, dass die Pagination mit den meisten Seiten auf das Modell aufgerufen wird.
Alternativ wäre eine robustere Methode, einen Volltext-Suchdienst hinzuzufügen (wie z. Indexpanzer, Web Solr, Denk Sphinx denken). Die Technologie für das, was für diese Bewegungen schnell heiß ist, recherchieren Sie also und finden Sie eine, die Ihren Bedürfnissen entspricht. Beispielsyntax dafür wäre so etwas wie:
User.multi_solr_search query, models: [Post, Comment]
Andere Tipps
Seit diesem Commit: https://github.com/amatsuda/kaminari/commit/f9f529fb68ab89feea38773a4c625c1b14859128
Sie können Folgendes machen
Aus Ihrer Ansicht können Sie dies tun:
<%= paginate @users, :remote => true, :param_name => "user_page" %>
<%= paginate @posts, :remote => true, :param_name => "post_page" %>
<%= paginate @comments, :remote => true, :param_name => "comment_#{some_post_id}_page" %>
Und dann können Sie in Ihrem Controller auf diese Weise auf sie verweisen:
@users = User.search(query).page(params[:user_page])
@posts = Post.search(query).page(params[:post_page])
@comments = Comment.search(query).page(params[:comment_page])
Und die js.erb Ihrer Ansicht haben vielleicht so etwas wie:
$('#posts').html('<%= escape_javascript render(@posts) %>');
$('.table-pager').html('<%= escape_javascript(paginate(@posts, :remote => true).to_s) %>');
Sie können die Ergebnisse der Abfrage kombinieren und darauf ausführen.
users = User.search(query)
posts = Post.search(query)
comments = Comment.search(query)
@results = users + posts + comments
@results.page(params[:page])