Rails ActiveRecord Проблема со сложным соединением - выбор не работает - PullRequest
3 голосов
/ 29 октября 2009

У меня есть два модельных объекта:

  • Событие
  • Место проведения

События имеют места проведения. Места могут иметь 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, я вижу, что я могу использовать mappable с: сквозной ассоциацией на Event, и должен иметь возможность вызывать искателей геокит на Event! Отлично (как вы можете видеть выше, я добавил act_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 секунды для запуска на моем рабочем столе! Но, приступая к этому, вот моя жалоба:

  • Чтобы попытаться улучшить производительность, вы можете видеть, что я пытался использовать инструкцию SELECT в моем запросе поиска ActiveRecord. Я просто хочу знать НАЗВАНИЯ этих событий, которые совпадают, а не все остальные поля. Но запрос проходит, и выбирает все из события! Он использует странные псевдонимы, с которыми я не знаком, например, 't1_r1'. Так что это явно проблема.

Кроме того, этот запрос, когда он выполняется только на объектах (т. Е. Отказ от соединения), выполняется менее чем за 10 мс. Так есть ли способ сначала выполнить поиск по местам, а затем объединить против событий? Я думаю, что объединение должно быть выполнено для двух таблиц в целом, и только тогда появляется часть геокодирования, которая сокращает набор данных.

Любая помощь в ужесточении этой проблемы будет принята с благодарностью (это некоммерческий проект). Я чувствую, что модель очень проста, я должен быть в состоянии сделать это без лишней суеты?

Заранее спасибо!

(Edit: в ранней версии этого поста я был глуп, Limit работал нормально, мой взгляд был сломан, отредактирован, чтобы убрать эту часть.)

1 Ответ

4 голосов
/ 29 октября 2009

Похоже, что acts_as_mappable использует стремительную загрузку функциональности Rails Active Record. Как только вы начинаете загружать, любой аргумент :select игнорируется, и вы не можете указать конкретные столбцы из таблицы / модели. В вашем случае я думаю, что это происходит из-за аргумента :through=>:venue для acts_as_mappable. Можете ли вы заставить его работать без сквозного аргумента? Вы также всегда можете просмотреть исходный код и посмотреть, есть ли какие-либо другие настройки, которые вы можете сделать.

...