在Thinking Sphinx中使用crc32调整has_many关系

时间:2013-05-04 13:05:25

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

实际上这很奇怪。我有两个模型彼此有has_many关系,这是我的模型

#model city
class City < ActiveRecord::Base
belong_to :state
end

#model state
class State < ActiveRecord::Base
has_many :city
end

我有州指数

ThinkingSphinx::Index.define 'state', :with => :active_record do
  indexes state_name, :sortable => true

  #here is the problem
  has "CRC32(cities.city_name)", :as => :city_name, :type => :integer
end

我想使用city_name作为过滤器。上面的代码不起作用,运行时出现错误信息

rake ts:index

这是错误消息

ERROR: index 'state_core': sql_range_query: Unknown column 'cities.city_name' in 'field list'

但是,当我将city_name放在索引块中时,如下所示,索引器运行良好!

ThinkingSphinx::Index.define 'state', :with => :active_record do
  indexes state_name, :sortable => true
  indexes cities.city_name
  has "CRC32(cities.city_name)", :as => :city_name, :type => :integer
end

有什么建议吗?

1 个答案:

答案 0 :(得分:3)

思考Sphinx无法判断您是否在SQL片段中引用关联表 - 所以在您的第一个示例中,没有任何迹象表明它需要在城市中加入。

索引定义中的join方法是出于此目的而存在的 - 因此,请尝试以下操作:

ThinkingSphinx::Index.define 'state', :with => :active_record do
  indexes state_name, :sortable => true

  has "CRC32(cities.city_name)", :as => :city_name, :type => :integer

  join cities
end

但是,值得注意的是:首先,您可能还需要在cities.city_name子句中添加GROUP BY,因为它不是任何聚合值的一部分:

# within index definition
group_by 'cities.city_name

但是:你的州模型有很多城市,而不仅仅是一个,所以它实际上应该聚合成一组整数值,而不仅仅是一个。这意味着您不需要group_by调用,但您需要自己添加聚合行为。这取决于您使用的是PostgreSQL还是MySQL:

# PostgreSQL
has "array_to_string(array_agg(crc32(cities.name)), ',')",
  :as => :city_names, :type => :integer, :multi => true

# MySQL
has "GROUP_CONCAT(CRC32(cities.name) SEPARATOR ',')",
  :as => :city_names, :type => :integer, :multi => true

CRC32不是PostgreSQL中的本机函数,因此您可能需要自己添加它。在v3之前思考Sphinx为你做了这个,但我重写了它,因此不再需要CRC32功能。这主要是因为CRC32可能导致碰撞,并且无法逆转,因此它是一种不优雅且不完美的解决方案。因此,我认为使用字段进行字符串比较会更好,但是这取决于您是否在应用中首选。

我会推荐这种方法:

ThinkingSphinx::Index.define :state, :with => :active_record do
  indexes state_name, :sortable => true

  has cities.id, :as => :city_ids
end

city = City.find_by_name('Melbourne')
State.search :with => {:city_ids => city.id}

它准确而优雅。