2011-09-25 5 views
9

레일스 용 강력한 Sunspot gem을 통해 사이트 전체 검색을 구현하려고합니다. 여기에는 여러 다른 모델을 한 번에 검색하는 작업이 포함됩니다. 내가 원하는 일은 faceting 기능을 사용하여 사용자가 각 모델에서 검색 결과를 필터링하거나 기본적으로 : boost 한정자로 정렬 된 서로 흩어져있는 같은 페이지에서 모두를 볼 수있게하는 것입니다. Sunspot Railscast의 faceting 코드와 다른 모델의 Stackoverflow question (복수 유형 코드는 Sunspot documentation에서 변형 됨)을 조합하여 여러 모델 검색 코드를 조합하면 효과가있을 것이라고 생각하는 해결책을 얻을 수 있지만 그렇지 않습니다.레일 Sunspot gem : 여러 모델의 사이트 전체 검색을 사용하는 패싯

여러 메서드 검색이 성공하지만 패싯이 항상 null로 표시됩니다. 기본적으로 각 모델의 가상 속성을 동일한 이름 인 search_class로 제공합니다.이 속성은 모델의 클래스 이름을 문자열로 렌더링 한 것입니다. 그런 다음이를 패싯으로 사용해보십시오. 그러나 뷰 로직에서 @ search.facet (: search_class) .rows)의 결과는 항상 빈 배열입니다. @ search.results가 반환 된 각 인스턴스가 동일한 쿼리에서 많은 모델을 반환 할 때를 포함하여 완벽하게 액세스 가능한 Instance.search_class 속성

난 Rails 3.1.0과 sunspot-rails 1.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> 
+0

왜 이런면을 사용합니까? 모든 가능한 클래스가 나열된 결과의 개수와 함께 선택 메뉴를 만들 수 있습니까? 그런 다음 검색 메소드를 호출하면 동적으로 관련 클래스를 검색 인수로 호출합니다. –

+0

데이터를 다시 색인 해 봤습니까? 그리고 흑점 파일에 데이터의 클래스 이름이 있는지 확인 했습니까? – Sebastien

답변

2

Sunspot.search (푸, 바) {와 (:에 관하여'); 면 (: 이름)}

당신이 F로 번역 facet(:name)가 나는 경우 당신은 solr/log/ solr_production.log 파일

에서 정확한 SOLR 쿼리를 찾을 수 있습니다 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 

를 다음으로 변환합니다. name_s .facet 및 아니요f.foo.facet and f.bar.facet. 그 이유는 예상대로 작동하지 않는 이유입니다.

다음은 작동하지만 각 모델에 3 개의 더미 메소드를 생성해야합니다. 아이디어는 각 유형에 대해 별도의 패싯 선이 필요하다는 것입니다.

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 쿼리 로그를보고 검색 문제를 디버그하는 것이 좋습니다. 태양 흑점은 많은 것들을 마법처럼 만듭니다. 그러나 한계가 있습니다 :-)

관련 문제