Cuando implementé esto en MySQL (para almacenar lugares en una esfera achatada, que es básicamente lo que es la tierra (¡supongo que estás hablando de la tierra!)), almacené la mayor cantidad de información precalculada posible en la base de datos. Entonces, para una fila que almacena latitude
y longitude
, también calculo en el momento de la inserción los siguientes campos:
radiansLongitude
(Math.toRadians(longitude)
)sinRadiansLatitude
(Math.sin(Math.toRadians(latitude)
)cosRadiansLatitude
(Math.cos(Math.toRadians(latitude)
)
Luego, cuando busco los lugares que están dentro de X unidades de la latitude
/longitude
en cuestión, mi declaración preparada es la siguiente:
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
Donde YYYY
=3965 te da las distancias en millas o YYYY
=6367 se puede utilizar para distancias en km.
Finalmente, he usado maximumSearchLatitude
/ maximumSearchLongitude
/ minimumSearchLongitude
/ maximumSearchLongitude
parámetros para excluir la mayoría de los puntos del conjunto de resultados antes de que la base de datos tenga que realizar cualquier cálculo. Puede o no necesitar esto. Si usa esto, dependerá de usted qué valores elija para estos parámetros, ya que dependerá de lo que esté buscando.
Obviamente, serán necesarias aplicaciones juiciosas de índices en la base de datos.
El beneficio de usar este enfoque es que la información que nunca cambia pero que se necesita cada vez solo se calcula una vez, mientras que el cálculo de los valores de radiansLongitude
, sinRadiansLatitude
, cosRadiansLatitude
porque cada fila cada vez que realice una búsqueda se volverá muy costosa muy rápido.
La otra opción es usar un índice geoespacial , lo que significa que la base de datos se encarga de todo esto. Sin embargo, no sé qué tan bien se integra Hibernate con eso.
Descargo de responsabilidad:hace mucho tiempo que no miré esto, ¡y no soy un experto en GIS!