Сохранение значений Lat Lng в MySQL с использованием Spatial Point Type
Используемая технология: MySQL 5.1 и PHP 5.3
Я просто разрабатываю новую базу данных для сайта, который я пишу. Я смотрю на лучший способ хранения значений Lat и Lng.
В прошлом я использовал DECIMAL и использовал PHP/MySQL в форме:
SQRT(POW(69.1 * (fld_lat - ( $lat )), 2) + POW(69.1 * (($lon) - fld_lon) * COS(fld_lat / 57.3 ), 2 )) AS distance
чтобы найти наиболее подходящие места.
Начиная читать больше о новых технологиях, мне интересно, следует ли использовать Spatial Extensions. http://dev.mysql.com/doc/refman/5.1/en/geometry-property-functions.html
Информация довольно тонкая на земле, хотя и возник вопрос о том, как хранить данные. Вместо использования DECIMAL я бы теперь использовал POINT в качестве типа данных?
Кроме того, как только он хранится как POINT, легко просто получить значения Lat Lng из него в случае, если я хочу построить его на карте, или я должен дополнительно сохранить lat lng как DECIMALS снова?
Я знаю, что я должен попробовать использовать PostGIS, поскольку большинство сообщений здесь говорят, что я просто не хочу изучать новую БД, хотя!
Последующие действия
Я играю с новым типом POINT. Я смог добавить значения Lat Lng, используя следующее:
INSERT INTO spatialTable (placeName, geoPoint) VALUES( "London School of Economics", GeomFromText( 'POINT(51.514 -0.1167)' ));
Затем я могу получить значения Lat и Lng из Db, используя:
SELECT X(geoPoint), Y(geoPoint) FROM spatialTable;
Это выглядит хорошо, однако расчет расстояния - это бит, который мне нужно решить. По-видимому, у MySQL есть место-держатель для функции расстояния, но не будет выпущен на некоторое время. В нескольких сообщениях я обнаружил, что мне нужно сделать что-то вроде ниже, но я думаю, что мой код немного ошибочен:
SELECT
placeName,
ROUND(GLength(
LineStringFromWKB(
LineString(
geoPoint,
GeomFromText('POINT(52.5177, -0.0968)')
)
)
))
AS distance
FROM spatialTable
ORDER BY distance ASC;
В этом примере geoPoint - это POINT, введенный в БД с использованием INSERT выше.
GeomFromText('POINT(52.5177, -0.0968)'
- значение Lat Lng. Я хочу рассчитать расстояние от.
Дальнейшее наблюдение
Скорее глупо, я просто положил в ROUND часть SQL, не подумав. Принимая это, я получаю:
SELECT
placeName,
(GLength(
LineStringFromWKB(
LineString(
geoPoint,
GeomFromText('POINT(51.5177 -0.0968)')
)
)
))
AS distance
FROM spatialTable
ORDER BY distance ASC
Который, кажется, дает мне правильные расстояния, которые мне нужны.
Я полагаю, что единственное, что в настоящее время нуждается в ответе, - это любые мысли о том, что я просто делаю жизнь трудной для себя, используя Spatial сейчас или будущую проверку себя...
Ответы
Ответ 1
Я думаю, что вы всегда должны легко использовать абстракцию самого высокого уровня. Если ваши данные геопространственны, используйте геопространственные объекты.
Но будьте осторожны. Mysql - худшая геопространственная база данных. Его ОК для точек, но все его многоугольные функции полностью сломаны - они меняют многоугольник на его ограничивающий прямоугольник, а затем делают ответ на это.
Худший пример, который поразил меня, состоит в том, что если у вас есть многоугольник, представляющий Японию, и вы спрашиваете, какие места находятся в Японии, Владивосток попадает в список!
Oracle и PostGIS не имеют этой проблемы. Я ожидаю, что MSSQL не будет, и любая база данных Java, использующая JTS в качестве своего движка, не будет. Геопространственное благо. MySQL Geospatial Bad.
Просто прочитайте здесь Как вы используете пространственные запросы MySQL, чтобы найти все записи в радиусе X?, что оно зафиксировано в 5.6.1.
Hoorah!
Ответ 2
Mysql GIS yagni:
Если у вас нет опыта работы с ГИС, изучение пространственных расширений практически похоже на изучение новой базы данных, а также небольшую математику и множество аббревиатур. Карты, прогнозы, сриды, форматы... Нужно ли вам все это рассчитать для расчета расстояний между точками, заданными с помощью определенного lat/long: возможно, нет, вы будете интегрировать сторонние данные ГИС или работать с чем-то более сложным, чем точки, что система координат вы будете использовать?
Возвращаясь к yagni: делайте все как можно проще, в этом случае реализуйте свой код в php или с помощью простого SQL. Как только вы достигнете барьера и решите, что вам нужна пространственная, ознакомьтесь с системой ГИС, системами координат, проектами и соглашениями.
К тому времени вам, вероятно, понадобится PostGIS.
Ответ 3
Это хорошо, потому что тогда вы можете использовать пространственные индексы для своих запросов. Ограничьте ограничительную рамку, например, чтобы ограничить количество строк для сравнения.
Ответ 4
Если вы можете добавить дополнительный код в свой сервер, используйте Geohash.
Он кодирует координату в строку таким образом, что префиксы обозначают более широкую область. Чем длиннее ваша строка, тем больше у вас будет.
И он имеет привязки для многих языков.
http://en.wikipedia.org/wiki/Geohash
https://www.elastic.co/guide/en/elasticsearch/guide/current/geohashes.html