2

其实很奇怪。我有两个相互具有 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

有什么建议么 ?

4

1 回答 1

3

Thinking 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_nameGROUP BY子句中,因为它不是任何聚合值的一部分:

# within index definition
group_by 'cities.city_name

而且:你的 State 模型有很多城市,而不仅仅是一个,所以它实际上应该聚合成一组整数值,而不仅仅是一个。这意味着您不需要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 中的本机函数,因此您可能需要自己添加它。Thinking Sphinx v3 之前的版本为您完成了此操作,但我已对其进行了重写,因此不再需要 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}

它准确而优雅。

于 2013-05-05T18:15:36.057 回答