Kiedy zaimplementowałem to w MySQL (do przechowywania miejsc na spłaszczonej sferze, czyli w zasadzie tym, czym jest Ziemia (zakładam, że mówisz o Ziemi!)), zachowałem w bazie danych tyle wstępnie obliczonych informacji, ile to możliwe. Tak więc dla wiersza, który przechowuje latitude
i longitude
, obliczam również w czasie wstawiania następujące pola:
radiansLongitude
(Math.toRadians(longitude)
)sinRadiansLatitude
(Math.sin(Math.toRadians(latitude)
)cosRadiansLatitude
(Math.cos(Math.toRadians(latitude)
)
Następnie, gdy szukam miejsc, które znajdują się w obrębie X jednostek latitude
/longitude
moje przygotowane oświadczenie brzmi następująco:
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
Gdzie YYYY
=3965 daje odległości w milach lub YYYY
=6367 może być użyte dla odległości w km.
Wreszcie użyłem maximumSearchLatitude
/ maximumSearchLongitude
/ minimumSearchLongitude
/ maximumSearchLongitude
parametry, aby wykluczyć większość punktów ze zbioru wyników, zanim baza danych będzie musiała wykonać jakiekolwiek obliczenia. Możesz tego potrzebować lub nie. Jeśli tego użyjesz, to od Ciebie zależy, jakie wartości wybierzesz dla tych parametrów, ponieważ będzie to zależeć od tego, czego szukasz.
Oczywiście konieczne będzie rozsądne stosowanie indeksów w bazie danych.
Zaletą tego podejścia jest to, że informacje, które nigdy się nie zmieniają, ale są potrzebne za każdym razem, są obliczane tylko raz, podczas gdy oblicza się wartości radiansLongitude
, sinRadiansLatitude
, cosRadiansLatitude
za każdy wiersz za każdym razem, gdy przeprowadzasz wyszukiwanie, bardzo szybko stanie się bardzo drogi.
Inną opcją jest użycie indeksu geoprzestrzennego , co oznacza, że wszystko to jest obsługiwane przez bazę danych. Nie wiem jednak, jak dobrze Hibernate się z tym integruje.
Zastrzeżenie:minęło dużo czasu, odkąd na to patrzyłem, a nie jestem ekspertem GIS!