使用thinking_sphinx进行搜索并过滤结果

时间:2010-12-02 20:06:23

标签: ruby-on-rails scope thinking-sphinx

我有这种情况,我认为这将是非常基本的,但发现我无法真正达到我的需要。这就是为什么我有一个think_sphinx专家的问题。

场景是这样的:我需要在公司列表中进行搜索,只返回那些拥有地址的公司(公司可以有很多地址)属于某个特定城市或者根本没有(我可以这样做) )。

我有以下型号:

class Company < ActiveRecord::Base
    has_many :company_addresses

    define_index
      indexes :name
      indexes :description
      indexes :keywords
    end
end

class CompanyAddress < ActiveRecord::Base
end

CompanyAddress有一个city_id属性。如果没有循环搜索狮身人面像搜索中的所有返回记录,是否有办法更容易地实现相同的目标?

我正在使用Rails 3.0.3和thinking_sphinx。

1 个答案:

答案 0 :(得分:4)

您需要添加指向公司的city_id值的属性:

has company_addresses.city_id, :as => :city_ids

然后您可以过滤属于特定城市的公司:

Company.search 'foo', :with => {:city_ids => @city.id}

如果您希望两个匹配到特定城市没有城市,这有点棘手,因为属性过滤器的OR逻辑充其量只是有点棘手。理想情况下,您需要的是包含0或所有城市ID的单个属性。这样做取决于您的数据库,因为MySQL和Postgres功能各不相同。

虽然这是一个粗略的想法 - 这可能适用于MySQL:

has "IF(COUNT(city_id) = 0, '0', GROUP_CONCAT(city_id SEPARATOR ',')",
  :as => :city_ids, :type => :multi

Postgres非常相似,但您可能需要使用CASE语句而不是IF,并且您肯定希望使用一些函数进行组连接:

array_to_string(array_accum(city_id, '0')), ',')

(array_accum由Thinking Sphinx提供,因为在PostgreSQL中没有直接等效的GROUP_CONCAT)。

无论如何,如果你需要这种方法,并且得到所有SQL,那么你的查询看起来像是:

Company.search 'foo', :with => {:city_ids => [0, @city.id]}

这将匹配0(代表没有城市)或特定城市。

最后:如果您未在正常字段和属性中的任何位置引用company_addresses关联,则需要强制加入define_index

join company_addresses

希望能提供足够的线索 - 随时在the Google Group继续讨论。