2011-09-25 12 views
9

Sto cercando di implementare una ricerca sul tutto il sito attraverso la potente gemma Sunspot per Rails. Ciò comporta una ricerca su più modelli molto diversi contemporaneamente. Ciò che VOGLIO fare è utilizzare la funzione di sfaccettatura per consentire all'utente di filtrare i risultati della ricerca su ciascun modello o, per impostazione predefinita, visualizzare tutti sulla stessa pagina, intercalati l'uno con l'altro ordinati dal qualificatore boost. Combinando il codice sfaccettato dal codice Sunspot Railscast con il codice di ricerca di più modelli da un altro Stackoverflow question (una variazione sul codice "Tipo multiplo" dal numero Sunspot documentation) mi ha fornito una soluzione che avrei pensato potesse funzionare, ma non lo è.Rails Sunspot gem: sfaccettature di utilizzo con più ricerche su tutto il sito modello

La ricerca di più metodi ha esito positivo, ma le faccette risultano sempre nulle. Il mio approccio di base è quello di fornire un attributo virtuale su ogni modello con lo stesso nome,: search_class, che è solo il nome della classe del modello reso in una stringa. Allora provo a usarlo come sfaccettatura. Tuttavia, nella logica della vista i risultati del facet (@ search.facet (: search_class) .rows) sono sempre un array vuoto, incluso quando @ search.results restituisce molti modelli diversi nella stessa query, nonostante ogni istanza restituita abbia un Attributo Instance.search_class perfettamente accessibile.

Utilizzo Rails 3.1.0 e sunspot-rails 1.2.1.

Cosa devo fare per far funzionare questo codice di sfaccettatura?

controllore:

#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 

Modelli:

#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 

Vista:

#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

Perché dovresti usare le sfaccettature per questo? Non puoi semplicemente creare un menu di scelta in cui sono elencate tutte le classi possibili con il numero di risultati che tutti hanno? Quindi quando chiamate il metodo di ricerca, chiamate dinamicamente la classe correlata come argomento per la ricerca? –

+0

Hai reindicizzato i tuoi dati? E hai controllato se i dati avevano il nome della classe nei file di sunspot? – Sebastien

risposta

2

Questo

Sunspot.search (Foo, Bar) {con (:Riguardo a'); sfaccettatura (: nome)}

traduce al seguente in 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 

È possibile trovare l'esatto interrogazione Solr nel solr/log/ solr_production.log file di

se si nota facet(:name) tradotto in f. name_s .facet e nonf.foo.facet and f.bar.facet. Ecco perché non ha funzionato come previsto.

Quanto segue funzionerà ma occorre uno per creare 3 metodi fittizi in ciascun modello. L'idea è che hai bisogno di una linea di sfaccettatura separata per ognuno dei tipi.

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 

Anche in questo caso, è sempre meglio esaminare il log delle query SOLR effettivo per eseguire il debug dei problemi di ricerca. Sunspot rende molte cose magiche ma ha i suoi limiti ;-)

Problemi correlati