У меня есть модель базы данных Position(lat,lon)
, которая содержит latitudes
и longitudes.
У меня есть действие с контроллером show_close_by
, которое получает позицию в градусах (my_lat, my_lon)
, допустимость (в километрах) и должна возвращать список позиций в базе данных, находящихся в пределах допустимого диапазона.
Для этого я использую формулу haversine_distance, которая вычисляет расстояние в километрах (на поверхности Земли) между двумя координатами (lat1, lon1, lat2, lon2)
.
Чтобы сделать запрос быстрее, я написал целую формулу haversine_distance
в запросе:
... WHERE 2*6371*asin(sqrt( power( sin( (:lat2-latitude)*pi()/(180*2) ) ,2) + cos(latitude*pi()/180)*cos(:lat2*pi()/180)*power(sin( (:lon2-longitude)*pi()/(180*2) ),2) )) < tolerance
Специфика запроса не имеет значения. Я сомневаюсь: необходимо ли вычислить эту огромную функцию для КАЖДОЙ позиции в базе данных? Могу ли я отфильтровать некоторые позиции, которые явно слишком далеки, с более простой функцией?
Ну, я могу: с вложенным SQL-запросом я могу запросить базу данных для позиций, которые находятся в большом "квадрате" (в пространстве lat/lon), а затем отфильтровывать те, у которых более затратная тригонометрическая функция. Что-то вроде следующего:
SELECT * FROM ( SELECT * FROM Positions WHERE lat-latitude < some_reasonable_upper_bound AND lon-longitude < same_upper_bound ) WHERE costly_haversine_distance < tolerance
Наконец, мой вопрос: как я могу реализовать это в Rails (без написания всего запроса сам)? Выполняет ли Positions.where(reasonable_upper_bound).where(costly_but_accurate_restriction)
вложенный запрос? Если нет, то как?
Спасибо большое!