web-dev-qa-db-fra.com

Stockage des valeurs Lat Lng dans MySQL en utilisant le type de point spatial

Technologie utilisée: MySQL 5.1 et PHP 5.3

Je suis en train de concevoir une nouvelle base de données pour un site que j'écris. Je cherche la meilleure façon de stocker maintenant les valeurs Lat et Lng.

Dans le passé, j'utilisais DECIMAL et j'utilisais une sélection PHP/MySQL sous la forme:

SQRT(POW(69.1 * (fld_lat - ( $lat )), 2) + POW(69.1 * (($lon) - fld_lon) * COS(fld_lat / 57.3 ), 2 )) AS distance

pour trouver les lieux correspondants les plus proches.

Commençant à en savoir plus sur les nouvelles technologies, je me demande si je devrais utiliser des extensions spatiales. http://dev.mysql.com/doc/refman/5.1/en/geometry-property-functions.html

Les informations sont assez minces sur le terrain et avaient une question sur la façon de stocker les données. Au lieu d'utiliser DECIMAL, est-ce que j'utiliserais maintenant POINT comme type de données?

De plus, une fois stocké en tant que POINT, est-il facile d'en obtenir les valeurs Lat Lng au cas où je souhaiterais le tracer sur une carte ou devrais-je également stocker les lat lngs en tant que DECIMALS?

Je sais que je devrais probablement utiliser PostGIS car la plupart des articles ici disent que je ne veux tout simplement pas apprendre une nouvelle base de données!

Suivi

J'ai joué avec le nouveau type POINT. J'ai pu ajouter des valeurs Lat Lng en utilisant les éléments suivants:

INSERT INTO spatialTable (placeName, geoPoint) VALUES( "London School of Economics", GeomFromText( 'POINT(51.514 -0.1167)' ));

Je peux ensuite récupérer les valeurs Lat et Lng du Db en utilisant:

SELECT X(geoPoint), Y(geoPoint) FROM spatialTable;

Tout cela semble bon, mais le calcul de la distance est le bit que je dois résoudre. Apparemment, MySQL a un espace réservé pour une fonction de distance mais ne sera pas publié avant un certain temps. Dans quelques articles, j'ai constaté que je devais faire quelque chose comme ci-dessous, mais je pense que mon code est légèrement faux:

SELECT
 placeName,
 ROUND(GLength(
  LineStringFromWKB(
   LineString(
    geoPoint, 
    GeomFromText('POINT(52.5177, -0.0968)')
  )
  )
))
AS distance
FROM spatialTable
ORDER BY distance ASC;

Dans cet exemple, geoPoint est un POINT entré dans la base de données à l'aide de l'INSERT ci-dessus.

GeomFromText('POINT(52.5177, -0.0968)' est une valeur Lat Lng dont je veux calculer la distance.

Plus de suivi

Plutôt bêtement, je venais de mettre la partie ROUND du SQL sans vraiment y penser. Le retirer me donne:

SELECT
placeName,
(GLength(
LineStringFromWKB(
  LineString(
    geoPoint, 
    GeomFromText('POINT(51.5177 -0.0968)')
  )
 )
))
AS distance
FROM spatialTable
ORDER BY distance ASC

Ce qui me donne les bonnes distances dont j'ai besoin.

Je suppose que la seule chose à laquelle il faut répondre actuellement est de savoir si je me rends la vie difficile en utilisant Spatial maintenant ou en me protégeant du futur ...

37
bateman_ap

Je pense que vous devriez toujours utiliser l'abstraction de plus haut niveau facilement disponible. Si vos données sont géospatiales, utilisez des objets géospatiaux.

Mais fais attention. Mysql est la pire base de données géospatiales qui existe. C'est OK pour les points, mais toutes ses fonctions de polygone sont complètement brisées - ils changent le polygone en son rectangle de délimitation, puis font la réponse à ce sujet.

Le pire exemple qui m'a frappé est que si vous avez un polygone représentant le Japon et que vous demandez quels sont les endroits au Japon, Vladivostok entre dans la liste!

Oracle et PostGIS n'ont pas ce problème. Je m'attends à ce que MSSQL ne le fasse pas et à aucune Java utilisant JTS comme moteur ne le fait pas. Géospatial Bon. MySQL Géospatial Mauvais.

Lisez simplement ici Comment utilisez-vous les requêtes spatiales MySQL pour trouver tous les enregistrements dans le rayon X? qui est corrigé dans 5.6.1.

Hoorah!

8
Julian

Si vous pouvez ajouter du code supplémentaire dans votre backend, utilisez Geohash.

Il code une coordonnée dans une chaîne de manière à ce que les préfixes désignent une zone plus large. Plus votre chaîne est longue, plus vous avez de précision.

Et il a des liaisons pour de nombreuses langues.

http://en.wikipedia.org/wiki/Geohashhttps://www.elastic.co/guide/en/elasticsearch/guide/current/geohashes.html

1
Vajk Hermecz

C'est une bonne chose, car vous pouvez alors utiliser des index spatiaux dans vos requêtes. Limitez à une zone de délimitation, par exemple, pour limiter le nombre de lignes à comparer.

1
aredridel

Mysql GIS yagni:

Si vous n'avez aucune expérience avec les SIG, l'apprentissage des extensions spatiales est pratiquement comme l'apprentissage d'une nouvelle base de données, plus un peu de mathématiques et beaucoup d'acronymes. Cartes, projections, srids, formats ... Faut-il apprendre tout cela pour calculer les distances entre des points donnés un certain lat/long: probablement pas, allez-vous intégrer des données SIG tierces ou travailler avec quelque chose de plus complexe que des points, quoi système de coordonnées utiliserez-vous?

Revenons à yagni: faites les choses aussi simplement que possible, dans ce cas implémentez votre code en php ou avec du SQL simple. Une fois que vous atteignez une barrière et décidez que vous avez besoin d'espace, lisez le système SIG, coordonnez les systèmes, les projets et les conventions.

D'ici là, vous voudrez probablement PostGIS.

1
ashwoods