У меня есть два модельных объекта:
События имеют места проведения. Места могут иметь 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 работал нормально, мой взгляд был сломан, отредактирован, чтобы убрать эту часть.)