Rails ActiveRecord复杂连接问题 - 选择不起作用

时间:2009-10-28 22:47:57

标签: sql ruby-on-rails activerecord geokit

我有两个模型对象:

  • 事件
  • 地点

活动有场地。场地可以举办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秒才能在我的桌面上运行!但要了解它,这是我的抱怨:

  • 为了尝试提高性能,您可以看到我尝试在ActiveRecord查找查询中使用SELECT语句。我只是想知道匹配的这些事件的标题,而不是所有其他字段。但查询通过,并从事件中选择所有内容!它使用我不熟悉的奇怪别名,如't1_r1'。所以这显然是个问题。

此外,此查询在单独对场地运行时(即取消JOIN)在不到10毫秒内执行。那么有没有办法首先进行Venues搜索,然后对事件进行联接?我认为连接必须在整个两个表上完成,然后只有地理编码部分进入并缩小数据集。

任何帮助收紧这个问题的人都会非常感激(这是一个非商业项目)。我觉得这个模型很简单我应该能够做到这一点而不用太大惊小怪?

提前致谢!

(编辑:在这篇文章的早期版本中,我是愚蠢的,限制工作正常,我的视图被破坏,编辑以取消该部分。)

1 个答案:

答案 0 :(得分:4)

看起来acts_as_mappable正在使用Rails Active Record的eager loading功能。一旦开始急切加载,任何:select参数都将被忽略,您无法从表/模型中指定特定列。在你的情况下,我认为这是因为:through=>:venue的{​​{1}}参数。如果没有通过论证,你能让它发挥作用吗?您也可以随时查看source code,看看是否还有其他调整。