Настройка таблицы широты и долготы MySQL
Я хочу сохранить значения широты и долготы мест в таблице базы данных mysql. Имея в виду будущее, я хочу иметь возможность найти эти места в определенном радиусе от определенного места. Сказав это, в каких типах данных я должен хранить значения широты и долготы? Пожалуйста, не могли бы вы предоставить мне сценарий создания таблицы для столбцов, например:
place_id | lat | long
возможно, в приведенной выше таблице отсутствует столбец, который предоставит мне дополнительные информация, которую я не могу видеть, мне нужна в настоящее время?
Спасибо за любую помощь.
2 ответов
вы должны хранить точки в столбце singe типа данных Point
который вы можете индексировать с помощью SPATIAL
index (если ваш тип таблицы MyISAM
):
CREATE SPATIAL INDEX sx_place_location ON place (location)
SELECT *
FROM mytable
WHERE MBRContains
(
LineString
(
Point($x - $radius, $y - $radius),
Point($x + $radius, $y + $radius)
)
location
)
AND Distance(Point($x, $y), location) <= $radius
это значительно улучшит скорость запросов, таких как"найти все в пределах заданного радиуса".
обратите внимание, что лучше использовать простой TM
метрические координаты (Восток и север) вместо полярных (широта и долгота). Для малых радиусов они достаточно точны, а расчеты упрощены значительно. Если все ваши точки в одном полушарию и находятся вдали от полюсов, вы можете использовать один центральный меридиан.
вы все еще можете использовать полярные координаты, но формулы расчета MBR
и расстояние будет более сложным.
я копал несколько часов через тонны тем и нигде не мог найти запрос, возвращающий точки в радиусе, определенном км. ST_Distance_Sphere делает это, однако сервер MariaDB 5.5 не поддерживает ST_Distance_Sphere ().
удалось заставить что-то работать, поэтому вот мое решение, совместимое с доктриной 2.5 и доктриной CrEOF Spatial Library:
$sqlPoint = sprintf('POINT(%f %f)', $lng, $lat);
$rsm = new ResultSetMappingBuilder($this->manager);
$rsm->addRootEntityFromClassMetadata('ApiBundle\Entity\Place', 'p');
$query = $this->manager->createNativeQuery(
'SELECT p.*, AsBinary(p.location) as location FROM place p ' .
'WHERE (6371 * acos( cos( radians(Y(ST_GeomFromText(?))) ) ' .
'* cos( radians( Y(p.location) ) ) * cos( radians( X(p.location) ) ' .
'- radians(X(ST_GeomFromText(?))) ) + sin( radians(Y(ST_GeomFromText(?))) ) * sin( radians( Y(p.location) ) ) )) <= ?',
$rsm
);
$query->setParameter(1, $sqlPoint, 'string');
$query->setParameter(2, $sqlPoint, 'string');
$query->setParameter(3, $sqlPoint, 'string');
$query->setParameter(4, $radius, 'float');
$result = $query->getResult();
предполагая, что lng и lat-это XY фиксированной точки, Place-это объект с полем " местоположение Тип точки. Я не мог использовать DQL непосредственно из-за проблем с привязкой param MySQL, поэтому низкоуровневый собственный запрос. Rsm требуется для сопоставления результатов в объекты сущности. Но жить без него можно.
Не стесняйтесь использовать его. Надеюсь, это сэкономит вам время.