Посмотрел статистику посещения сайта Кафе Ульяновска и понял, что порядка 30% посетителей приходят к нам через поисковик на страницу с конкретным описанием кафешки, получают нужную информацию и уходят восвояси.
«Непорядок» решили мы и поставили новую задачу — отображать на странице кафешки ближайшие заведения.
На самом деле было 2 цели:
1. ненавязчиво предложить походить по сайту.
2. дать людям выбор, если им кафешка не понравится
Но ближайшие заведения — понятие расплывчатое. Конкретизировали, оказалось, что по мнению большинства «ближайшие» — это на расстоянии пары минут ходьбы (чтобы машину не перепарковывать).
2 минуты ходьбы (при скорости 5км/ч) — это 170 метров. Округлили до 200 (чего уж там). И уперлись в новую проблему — как точно «вешать в метрах», если у нас есть только широта и долгота сайта.
Немного математики за 5й класс, и мы смогли перевести градусы в метры для Ульяновска.
UPDATE:
lat и lng — названия соответствующих полей в таблице
$row['lat'] и $row['lng'] — координаты точки, вокруг которой мы ищем
110349.7867154 — коэффициент, переводящий градусы широты в метры для Ульяновска
64505.305504 — коэффициент, переводящий градусы долготы в метры для Ульяновска
UPDATE2:
спасибо KAndy и homm. Благодаря их предложениям на тестовой машине запрос обрабатывается в 2 раза быстрее ( 0.0040 вместо 0.0084)
перед запросом немного оптимизируем
Этот запрос достает список ближайших маркеров из базы. Несмотря на его громоздкость, он отрабатывает на нашей таблице из 150 заведений всего за 0,004 секунды.
Можете посмотреть результат: Ресторан, кафе, бар Товарищ Сухов в Ульяновске под фотографиями. Красоту на этот список пока не навели, извиняйте :)
«Непорядок» решили мы и поставили новую задачу — отображать на странице кафешки ближайшие заведения.
На самом деле было 2 цели:
1. ненавязчиво предложить походить по сайту.
2. дать людям выбор, если им кафешка не понравится
Но ближайшие заведения — понятие расплывчатое. Конкретизировали, оказалось, что по мнению большинства «ближайшие» — это на расстоянии пары минут ходьбы (чтобы машину не перепарковывать).
2 минуты ходьбы (при скорости 5км/ч) — это 170 метров. Округлили до 200 (чего уж там). И уперлись в новую проблему — как точно «вешать в метрах», если у нас есть только широта и долгота сайта.
Немного математики за 5й класс, и мы смогли перевести градусы в метры для Ульяновска.
$sql="
SELECT *,
sqrt(POWER(((lat-".$row['lat'].")*110349.7867154), 2) + POWER(((lng-".$row['lng'].")*64505.305504), 2)) as `distance`
FROM `cafe`
WHERE
sqrt(POWER(((lat-".$row['lat'].")*1110349.7867154), 2) + POWER(((lng-".$row['lng'].")*64505.305504), 2)) < 200
ORDER BY `distance` ASC
";
UPDATE:
lat и lng — названия соответствующих полей в таблице
$row['lat'] и $row['lng'] — координаты точки, вокруг которой мы ищем
110349.7867154 — коэффициент, переводящий градусы широты в метры для Ульяновска
64505.305504 — коэффициент, переводящий градусы долготы в метры для Ульяновска
UPDATE2:
спасибо KAndy и homm. Благодаря их предложениям на тестовой машине запрос обрабатывается в 2 раза быстрее ( 0.0040 вместо 0.0084)
перед запросом немного оптимизируем
$distanceSq = $distance^2;
$row['latMin'] = $row['lat'] - 200/1110349.7867154;
$row['latMax'] = $row['lat'] + 200/1110349.7867154;
$row['lngMin'] = $row['lng'] - 200/64505.305504;
$row['lngMax'] = $row['lng'] + 200/64505.305504;
$sql="
SELECT *,
sqrt(POWER(((lat-".$row['lat'].")*110349.7867154), 2) + POWER(((lng-".$row['lng'].")*64505.305504), 2)) as `distance`
FROM `cafe`
WHERE
(lat >= ".$row['latMin']." AND lat <= ".$row['latMax'].")
AND (lng >= ".$row['lngMin']." AND lng <= ".$row['lngMax'].")
AND POWER(((lat-".$row['lat'].")*1110349), 2) + POWER(((lng-".$row['lng'].")*64505), 2) < ".$distanceSq."
ORDER BY `distance` ASC
";
Этот запрос достает список ближайших маркеров из базы. Несмотря на его громоздкость, он отрабатывает на нашей таблице из 150 заведений всего за 0,004 секунды.
Можете посмотреть результат: Ресторан, кафе, бар Товарищ Сухов в Ульяновске под фотографиями. Красоту на этот список пока не навели, извиняйте :)