3

我有两个模型对象:

  • 事件
  • 场地

活动有场地。场地可以有 1..* 事件。

场地有一个位置,一个经纬度,我使用 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,我发现我可以使用可映射的:通过事件关联,并且应该能够在 Event 上调用 geokit finder!非常好(所以你可以在上面看到,我已经添加了acts_as_mappable :through 到事件中)。

这是我的 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 语句。我只想知道匹配的这些事件的标题,而不是所有其他字段。但是查询通过了,并从 Event! 中选择了所有内容!它使用我不熟悉的奇怪别名,例如“t1_r1”。所以这显然是一个问题。

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

任何有助于加强这个问题的帮助将不胜感激(这是一个非商业项目)。我觉得模型很简单我应该可以不用大惊小怪地做到这一点?

提前致谢!

(编辑:在这篇文章的早期版本中,我很愚蠢,Limit 工作得很好,我的观点被打破了,编辑删除了那部分。)

4

1 回答 1

4

看起来acts_as_mappable正在使用 Rails Active Record 的急切加载功能。一旦你开始预先加载,任何:select参数都会被忽略,并且你不能从表/模型中指定特定的列。在你的情况下,我认为这是:through=>:venue因为acts_as_mappable. 你能在没有 through 参数的情况下让它工作吗?您也可以随时查看源代码,看看是否可以进行任何其他调整。

于 2009-10-28T23:27:49.393 回答