Алгоритмы / Найти соседей на Google Maps

Посмотрел статистику посещения сайта Кафе Ульяновска и понял, что порядка 30% посетителей приходят к нам через поисковик на страницу с конкретным описанием кафешки, получают нужную информацию и уходят восвояси.

«Непорядок» решили мы и поставили новую задачу — отображать на странице кафешки ближайшие заведения. На самом деле было 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 секунды.

Можете посмотреть результат: Ресторан, кафе, бар Товарищ Сухов в Ульяновске под фотографиями. Красоту на этот список пока не навели, извиняйте :)


AD: Занимаетесь гостиничным бизнесом - мебель для кафе . Магазины мебели в Москве.