2011-09-25 25 views
9

我試圖通過Rails的強大的黑子寶石來實現全站搜索。這涉及到一次搜索多個非常不同的模型。我想要做的是使用faceting功能來允許用戶在每個模型上過濾他們的搜索結果,或者默認情況下在同一頁面上查看所有內容,這些內容與由boost限定符排序的對方相互穿插。將來自Sunspot Railscast的分面代碼與來自另一個Stackoverflow question(來自Sunspot documentation的'多種類型'代碼的變體)的多模型搜索代碼相結合,給了我一個我認爲會起作用的解決方案,但卻沒有。Rails黑子寶石:使用多個模型全站搜索的方面

多重方法搜索成功,但小面總是變爲空。我的基本方法是爲每個模型提供一個相同名稱的虛擬屬性:search_class,它只是將模型的類名渲染爲字符串。然後我嘗試使用它作爲一個方面。然而,在視圖邏輯中,facet(@ 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(美孚,酒吧){具有(:關於');面(:名稱)}

轉化爲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/log/ solr_production.log文件

確切Solr的查詢,如果您發現facet(:name)翻譯到f。 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查詢日誌來調試搜索問題。太陽黑子使許多事情變得神奇,但它有其侷限性;-)

相關問題