试图访问sphinx内部数据

时间:2014-04-14 10:56:43

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

我有一张国家桌子(下面列出的型号)。我正在添加思维狮身人面像作为搜索,并希望用它来显示结果。

country.rb

class Country < ActiveRecord::Base
  has_many  :provinces
  has_many  :cities
  has_many  :zones
  has_many  :users
  attr_accessible :alpha_2, :alpha_3, :country_name, :numeric, :country_active

  scope :ordered, order("country_name")
  scope :active, where(:country_active => true)

end

country_index.rb

ThinkingSphinx::Index.define :country, :with => :active_record do
  indexes country_name, :sortable => true

  has created_at, updated_at
  has "(select COUNT(provinces.id) from provinces where provinces.country_id = id)", :as => :province_count, :type => :integer
end

在我看来,如果该国的省份数大于0,我需要向属于某个国家的省份添加条件链接。

count = country.provinces.count
if count > 0
    link_to(country.country_name, provinces_path(:id => country.id))
else
    country.country_name
end

我尝试用

替换计数的活动记录查询
count = Country.search(:select => "province_count", :with => {:country_name => country.country_name})

但尚未成功实现此功能。如何实现这一目标。我正在处理this link

1 个答案:

答案 0 :(得分:1)

需要注意的两件事应该有助于解决这个问题:

首先,您可以通过在索引定义中使用join方法强制关联联接 - 这样可以节省对完整子查询的需求:

ThinkingSphinx::Index.define :country, :with => :active_record do
  indexes country_name, :sortable => true

  has created_at, updated_at
  has "COUNT(provinces.id)", :as => :province_count, :type => :integer

  join provinces
end

其次,更重要的是,如果您希望在使用搜索结果时访问Sphinx属性,则需要使用Thinking Sphinx窗格来实现此目的:

search = Country.search(:with => {:sphinx_internal_id => country.id})
search.context[:panes] << ThinkingSphinx::Panes::AttributesPane
count = search.first.sphinx_attributes['province_count']

您会注意到我使用主键而不是国家/地区名称进行过滤 - ID更具体,因此您最终会获得特定匹配项,而且国家/地区名称是字段,而不是属性,因此,要按字段过滤,请使用:conditions代替:with。如果属性,则无法按其进行过滤,因为Sphinx不支持字符串属性的过滤器。

请注意,将这三行复制并粘贴到Rails控制台中将不起作用,因为控制台不仅评估行,而且输出结果,并输出搜索结果调用Sphinx调用 - 因此窗格不会适当应用。解决方法是在第一行的末尾包含; '',因此获得输出的结果是空字符串:

search = Country.search(:with => {:sphinx_internal_id => country.id}); ''
search.context[:panes] << ThinkingSphinx::Panes::AttributesPane
count = search.first.sphinx_attributes['province_count']

如果您实际上正在进行广泛搜索,而不仅仅是针对特定国家/地区,并且您希望每个国家/地区都计入省份,则可以在此处停止阅读。删除过滤器,但请确保添加窗格,然后就可以了。

但是,如果你真的只在一个国家/地区的记录中运行它......

您可以进一步简化事情 - 毕竟,您只想要计数,而不是实际的Country对象:

search = Country.search(
  :with       => {:sphinx_internal_id => country.id},
  :middleware => ThinkingSphinx::Middlewares::RAW_ONLY
)
search.first['province_count']

但是真的,如果你已经拥有了国家/地区对象,那么为了获得省份数量而进行搜索只会让我觉得有点过分。您只需拨打country.provinces.count,或使用ActiveRecord的counter_cache选项,然后在您的国家/地区型号上添加provinces_count列 - 从长远来看,毫无疑问这是最快的选择。

(对不起,这个答案的结果比我预期的要长得多 - 但它涵盖了几个不同的途径。)