实际上这很奇怪。我有两个模型彼此有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
有什么建议吗?
答案 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}
它准确而优雅。