我有两个模型对象:
活动有场地。场地可以举办1场*活动。
Venues有一个位置,一个lat和long,我和Geokit Rails插件一起使用。以下是这些模型在Rails中的样子:
class Event < ActiveRecord::Base
belongs_to :venue
acts_as_mappable :through => :venue
end
和
class Venue < ActiveRecord::Base
has_many :events
acts_as_mappable
end
很简单!现在,我想运行一个查询,我想在某个区域的几英里范围内找到所有事件,查看Geokit API,我看到我可以使用mappable:通过关联事件,并且应该能够在Event上调用geokit finders!很好(所以你可以看到上面,我已经添加了acts_as_mappable:直到事件)。
这是我的ActiveRecord查询:
Event.find(:all, :origin => [lat, lng], :select => 'title', :within => 5, :limit => 10)
这是SQL生成的:
SELECT `events`.`id` AS t0_r0, `events`.`title` AS t0_r1, `events`.`description` AS t0_r2,
`events`.`created_at` AS t0_r3, `events`.`updated_at` AS t0_r4, `events`.`venue_id` AS
t0_r5, `events`.`event_detail_id` AS t0_r6, `events`.`event_detail_type` AS t0_r7,
`venues`.`id` AS t1_r0, `venues`.`name` AS t1_r1, `venues`.`lat` AS t1_r2, `venues`.`lng`
AS t1_r3, `venues`.`created_at` AS t1_r4, `venues`.`updated_at` AS t1_r5 FROM `events` LEFT
OUTER JOIN `venues` ON `venues`.id = `events`.venue_id WHERE
(((venues.lat>51.4634898826039 AND venues.lat>51.5533406301823 AND venues.lng>-
0.197713629915149 AND venues.lng<-0.053351862714855)) AND
((ACOS(least(1,COS(0.898991438708539)*COS(-0.00219095974226756)*COS(RADIANS(venues.lat))*COS(RADIANS(venues.lng))
COS(0.898991438708539)*SIN(-
0.00219095974226756)*COS(RADIANS(venues.lat))*SIN(RADIANS(venues.lng))
SIN(0.898991438708539)*SIN(RADIANS(venues.lat))))*6376.77271)
<= 5)) LIMIT 10
哎哟。好吧,这需要相当长的时间才能运行,而且不仅仅是数学,我认为这里有一个重要的性能问题,这需要2秒才能在我的桌面上运行!但要了解它,这是我的抱怨:
此外,此查询在单独对场地运行时(即取消JOIN)在不到10毫秒内执行。那么有没有办法首先进行Venues搜索,然后对事件进行联接?我认为连接必须在整个两个表上完成,然后只有地理编码部分进入并缩小数据集。
任何帮助收紧这个问题的人都会非常感激(这是一个非商业项目)。我觉得这个模型很简单我应该能够做到这一点而不用太大惊小怪?
提前致谢!
(编辑:在这篇文章的早期版本中,我是愚蠢的,限制工作正常,我的视图被破坏,编辑以取消该部分。)
答案 0 :(得分:4)
看起来acts_as_mappable
正在使用Rails Active Record的eager loading功能。一旦开始急切加载,任何:select
参数都将被忽略,您无法从表/模型中指定特定列。在你的情况下,我认为这是因为:through=>:venue
的{{1}}参数。如果没有通过论证,你能让它发挥作用吗?您也可以随时查看source code,看看是否还有其他调整。