Lorsque j'ai implémenté cela dans MySQL (pour stocker des lieux sur une sphère oblate, qui est essentiellement ce qu'est la terre (je suppose que vous parlez de la terre !)), j'ai stocké autant d'informations pré-calculées que possible dans la base de données. Donc, pour une ligne qui stocke latitude
et longitude
, je calcule également au moment de l'insertion les champs suivants :
radiansLongitude
(Math.toRadians(longitude)
)sinRadiansLatitude
(Math.sin(Math.toRadians(latitude)
)cosRadiansLatitude
(Math.cos(Math.toRadians(latitude)
)
Ensuite, lorsque je recherche les lieux situés à moins de X unités de la latitude
/longitude
en question, ma déclaration préparée est la suivante :
from Location l where
acos(
sin(:latitude) * sinRadiansLatitude +
cos(:latitude) * cosRadiansLatitude *
cos(radiansLongitude - :longitude)
) * YYYY < :distance
and l.latitude>:minimumSearchLatitude
and l.latitude<:maximumSearchLatitude
and l.longitude>:minimumSearchLongitude
and l.longitude<:maximumSearchLongitude
order by acos(
sin(:latitude) * sinRadiansLatitude +
cos(:latitude) * cosRadiansLatitude *
cos(radiansLongitude - :longitude)
) * YYYY asc
Où YYYY
=3965 vous donne les distances en miles ou YYYY
=6367 peut être utilisé pour les distances en km.
Enfin, j'ai utilisé le maximumSearchLatitude
/ maximumSearchLongitude
/ minimumSearchLongitude
/ maximumSearchLongitude
paramètres pour exclure la majorité des points du jeu de résultats avant que la base de données n'ait à effectuer des calculs. Vous pouvez ou non en avoir besoin. Si vous l'utilisez, ce sera à vous de choisir les valeurs que vous choisirez pour ces paramètres, car cela dépendra de ce que vous recherchez.
Évidemment, des applications judicieuses des index dans la base de données seront nécessaires.
L'avantage d'utiliser cette approche est que les informations qui ne changent jamais mais qui sont nécessaires à chaque fois ne sont calculées qu'une seule fois, alors que le calcul des valeurs de radiansLongitude
, sinRadiansLatitude
, cosRadiansLatitude
pour chaque ligne chaque fois que vous effectuez une recherche va devenir très cher très rapidement.
L'autre option consiste à utiliser un index géospatial , ce qui signifie que tout cela est pris en charge pour vous par la base de données. Je ne sais pas dans quelle mesure Hibernate s'intègre à cela.
Avis de non-responsabilité :cela fait longtemps que je n'ai pas regardé cela, et je ne suis pas un expert en SIG !