ruby-on-rails - Rails Sunspot gem : Usings facets with multiple model site-wide searches

标签 ruby-on-rails solr sunspot faceted-search sunspot-rails

我正在尝试通过功能强大的Sunspot gem for Rails在整个站点范围内进行搜索。这涉及一次搜索多个非常不同的模型。我想做的是使用构面功能,使用户可以过滤每个模型上的搜索结果,或者默认情况下在同一页面上查看所有结果,并按:boost限定词排列。将Sunspot Railscast中的构面代码与另一个Stackoverflow question中的多模型搜索代码相结合(是Sunspot documentation中“Multiple Type”代码的一种变体),为我提供了一个我认为可行的解决方案,但无效。

多种方法搜索成功,但是构面始终变为null。我的基本方法是在每个模型上通过相同的名称提供一个虚拟属性:search_class,即将模型的类名称渲染为字符串。然后,我尝试将其用作构面。但是,在 View 逻辑中,构面(@ search.facet(:search_class).rows)的结果始终为空数组,包括@ search.results在同一查询中返回许多不同模型时,尽管每个返回的实例都有一个完全可访问的Instance.search_class属性。

我正在使用Rails 3.1.0和sunspot-rails 1.2.1。

我应该怎么做才能使这些构面代码起作用?

Controller :

#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>

最佳答案



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/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查询日志以调试搜索问题。太阳黑子使许多事物变得神奇,但它有其局限性;-)

关于ruby-on-rails - Rails Sunspot gem : Usings facets with multiple model site-wide searches,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7542924/

相关文章:

mysql - Ruby on Rails。无法在数据库中创建记录

ruby-on-rails - 将 utf8 字符串存储在数据库中,但验证和参数化音译

ruby-on-rails - Sunspot Solr 指定偏移量和限制

ruby-on-rails - 按预定顺序加载 CSS 文件

javascript - 在搜索文本框中输入日期值时如何避免 ajax 错误?

solr - 拼写检查导致 Core Reload 挂起

Solr 对动态列进行排序

solr - SolrCloud中configname设置的目的是什么

ruby - 太阳黑子 `LIKE` 查询

solr - 400 错误请求 : unknown field 'type'