从多模型查询中收集搜索结果

时间:2016-02-18 14:37:02

标签: ruby-on-rails search elasticsearch controller enumerable

我目前正在使用searchkick gem为搜索查询建立索引。还应注意,我正在搜索两个模型ArtistsAlbums。在我的search_controller我有3个实例变量,首先是@results,用于返回我autocomplete的两个模型的所有结果(在其他地方使用):

@results = Artist.search(params[:query], index_name: [Artist.searchkick_index.name, Album.searchkick_index.name], fields: [{ name: :word_start }], limit: 10)

然后有我的@artists/@albums个实例变量。

@artists = @results.select { |result| result.class.name == "Artist" }
@albums = @results.select { |result| result.class.name == "Album" }

我将这些结果分开,以便我可以在索引视图中对艺术家和专辑进行分组:

<h1>Search Results</h1>

<div class="artist-results">
  <h2>Artists</h2>

  <% @artists.each do |artist| %>
    <%= link_to artist.name, artist_path(artist) %>
  <% end %>
</div>

<div class="album-results">
  <h2>Albums</h2>

  <% @albums.each do |album| %>
    <%= link_to album.name, album_path(album) %>
  <% end %>
</div>

我对搜索控制器代码的主要关注点是我执行了两个几乎完全相同的枚举。我可能错了,但有些东西告诉我,我不应该这样做。对于我正在做的事情,是否有更高效的解决方案?我是否在正确的轨道上?

完整控制器代码

class SearchController < ApplicationController
  before_filter :set_results

  def index
  end

  def autocomplete
    render json: @results
  end

  private
    def set_results
      @results = Artist.search(params[:query], index_name: [Artist.searchkick_index.name, Album.searchkick_index.name], fields: [{ name: :word_start }], limit: 10)
      @artists = @results.select { |result| result.class.name == "Artist" }
      @albums = @results.select { |result| result.class.name == "Album" }
    end
end

1 个答案:

答案 0 :(得分:1)

不确定它的性能更高。但您可以使用group by

results = Artist.search(params[:query], index_name: [Artist.searchkick_index.name, Album.searchkick_index.name], fields: [{ name: :word_start }], limit: 10)
@grouped_results = results.group_by{|x| x.class.name }

然后

<h1>Search Results</h1>

<% @grouped_results.each do |class_name, results| %>
  <div class="<%= class_name.downcase %>-results">
    <h2><%= class_name.pluralize %></h2>

    <% results.each do |result| %>
      <%= link_to result %>
    <% end %>    
  </div>
<% end %>