Если вы собираетесь выполнять поиск на основе расстояния / геолокации, используйте геопространственные данные MySQL.Это гораздо эффективнее, чем прямая формула haversine.
Это всего лишь некоторые фрагменты, но они должны помочь вам встать на путь удивительности:
Прежде всего вашему столу понадобится геопространственный столбец для хранения широты / долготы, мой называется координатой инаходится на типе point
:
`coordinate` point NOT NULL,
далее вам нужно будет добавить геопространственный индекс:
SPATIAL KEY `coordinate` (`coordinate`)
(оба они являются частью моей таблицы, создают синтаксис sql).
Этот бит поможет вставить данные широты / долготы в столбец координат:
$data['coordinate'] = ("GeomFromText( 'POINT({$data['longitude']} {$data['latitude']})')");
Этот бит заменит вычисление расстояния (как часть более крупного запроса SQL):
$sql = str_replace(
array('%LATITUDE%','%LONGITUDE%'),
array($latitude, $longitude),
'(GLength( LineString( coordinate ,Point(%LONGITUDE%, %LATITUDE%)))) AS distance'
);
Приведенный выше запрос хорош для евклидовой геометрии (т. Е. Мир плоский), но мир не так, поэтому вам следует использовать приведенное ниже, чтобы помочь сузить список результатов.Для реальной точности и правильного упорядочения используйте формулу haversine или лучше для результатов, которые возвращаются из этих двух SQL-запросов.
Этот бит будет действовать как ограничивающий прямоугольник / прямоугольник (что-либо, находящееся вне поля, не будетвозвращенный - используйте его для замены HAVING distance <= '10'
, вы найдете запрос быстрее - особенно с большим количеством данных).Мои расчеты для max / min lat / lon являются лишь примерами, вы можете сделать лучше :-):
$minLat = $latitude - 0.5;
$maxLat = $latitude + 0.5;
$minLon = $longitude - 0.5;
$maxLon = $longitude + 0.5;
$sql = str_replace(
array('%MINLAT%', '%MAXLAT%','%MINLON%', '%MAXLON%'),
array($minLat, $maxLat, $minLon, $maxLon),
"MBRCONTAINS(GeomFromText('POLYGON((%MINLON% %MAXLAT%,%MAXLON% %MAXLAT%,%MAXLON% %MINLAT%,%MINLON% %MINLAT%, %MINLON% %MAXLAT%))'), `coordinate`)"
);