9

Rails用の強力なSunspotgemを介してサイト全体の検索を実装しようとしています。これには、複数の非常に異なるモデルを一度に検索することが含まれます。私がやりたいのは、ファセット機能を使用して、ユーザーが各モデルで検索結果をフィルタリングできるようにすることです。デフォルトでは、:boost修飾子で並べ替えて、すべて同じページに表示します。Sunspot Railscastのファセットコードを別のStackoverflow質問の複数モデル検索コード( Sunspotドキュメントの「MultipleType」コードのバリエーション)と組み合わせると、うまくいくと思うがうまくいかない解決策が得られました。

複数メソッドの検索は成功しますが、ファセットは常にnullになります。私の基本的なアプローチは、同じ名前:search_classで各モデルに仮想属性を提供することです。これは、文字列にレンダリングされたモデルのクラス名です。次に、それをファセットとして使用してみます。ただし、ビューロジックでは、ファセット(@ search.facet(:search_class).rows)の結果は常に空の配列です。これには、@ search.resultsが同じクエリで多くの異なるモデルを返す場合も含まれますが、返された各インスタンスには完全にアクセス可能なInstance.search_class属性。

Rails3.1.0とsunspot-rails1.2.1を使用しています。

このファセットコードを機能させるにはどうすればよいですか?

コントローラ:

#searches_controller.rb
class SearchesController < ApplicationController

  def show
    @search = search(params[:q])
    @results = @search.results
  end

  protected
  def search(q)
    Sunspot.search Foo, Bar, CarlSagan do
      keywords q
      #provide faceting for "search class", a field representing a pretty version of the model name
      facet(:search_class)
      with(:search_class, params[:class]) if params[:class].present?
      paginate(:page => params[:page], :per_page => 30)
    end
  end

end

モデル:

#Foo.rb
class Foo < ActiveRecord::Base
  searchable do
    text :full_name, :boost => 5
    text :about, :boost => 2
    #string for faceting
    string :search_class
  end

  #get model name, and, if 2+ words, make pretty
  def search_class
    self.class.name#.underscore.humanize.split(" ").each{|word| word.capitalize!}.join(" ")
  end
end

#Bar.rb
class Bar < ActiveRecord::Base
  searchable do
    text :full_name, :boost => 5
    text :about, :boost => 2
    #string for faceting
    string :search_class
  end

  #get model name, and, if 2+ words, make pretty
  def search_class
    self.class.name.underscore.humanize.split(" ").each{|word| word.capitalize!}.join(" ")
  end
end

#CarlSagan.rb
class CarlSagan < ActiveRecord::Base
  searchable do
    text :full_name, :boost => 5
    text :about, :boost => 2
    #string for faceting
    string :search_class
  end

  #get model name, and, if 2+ words, make pretty
  def search_class
    self.class.name#.underscore.humanize.split(" ").each{|word| word.capitalize!}.join(" ")
  end
end

意見:

#searches/show.html.erb
<div id="search_results">
<% if @results.present? %> # If results exist, display them

            # If Railscasts-style facets are found, display and allow for filtering through params[:class]
    <% if @search.facet(:search_class).rows.count > 0 %>
        <div id="search_facets"> 
          <h3>Found:</h3>  
          <ul>  
            <% for row in @search.facet(:search_class).rows %>  
              <li>  
                <% if params[:class].blank? %>  
                  <%= row.count %>  <%= link_to row.value, :class => row.value %>
                <% else %>  
                  <strong><%= row.value %></strong> (<%= link_to "remove", :class => nil %>)  
                <% end %>  
              </li>  
            <% end %>  
          </ul>  
        </div>
    <% end %>


    <% @results.each do |s| %>
        <div id="search_result">
            <% if s.class.name=="Foo"%>
                <h5>Foo</h5>
                <p><%= link_to s.name, foo_path(s) %></p>
            <% elsif s.class.name=="Bar"%>
                <h5>Bar</h5>
                <p><%= link_to s.name, bar_path(s) %></p>
            <% elsif s.class.name=="CarlSagan"%>
                <h5>I LOVE YOU CARL SAGAN!</h5>
                <p><%= link_to s.name, carl_sagan_path(s.user) %></p>
            <% end %>
        </div>
    <% end %>

<% else %>
    <p>Your search returned no results.</p>
    <% end %>
</div>
4

1 に答える 1

2

これ

Sunspot.search(Foo、Bar){with(:about、'a'); facet(:name)}

Solrでは次のように変換されます

INFO: [] webapp=/solr path=/select params={facet=true&start=0&q=*:*&f.name_s.facet.mincount=1&facet.field=name_s&wt=ruby&fq=type:(Foo+OR+Bar)&fq=about_s:a&rows=30} hits=1 status=0 QTime=1 

正確なSolrクエリはsolr/log/ solr_production.logファイルにあります

facet(:name)fに翻訳されていることに気付いた場合。name_s.facetではなく f.foo.facet and f.bar.facet. 、それが期待どおりに機能しなかった理由です。

以下は機能しますが、各モデルに3つのダミーメソッドを作成するために1つ必要です。アイデアは、タイプごとに個別のファセットラインが必要であるということです。

Sunspot.search Foo, Bar, CarlSagan do
  keywords q
  #provide faceting for "search class", a field representing a pretty version of the model name
  facet(:foo)
  facet(:bar)
  facet(:carlsagan)
  with(:search_class, params[:class]) if params[:class].present?
  paginate(:page => params[:page], :per_page => 30)
end

繰り返しになりますが、検索の問題をデバッグするには、実際のSOLRクエリログを確認することをお勧めします。黒点は多くのことを魔法のようにしますが、それには限界があります;-)

于 2012-03-02T20:48:26.030 に答える