När jag har implementerat detta i MySQL (för att lagra platser på en oblate sfär, vilket i princip är vad jorden är (jag antar att du pratar om jorden!)), har jag lagrat så mycket föruträknad information som möjligt i databasen. Så, för en rad som lagrar latitude
och longitude
, jag beräknar även vid insättningstillfället följande fält:
radiansLongitude
(Math.toRadians(longitude)
)sinRadiansLatitude
(Math.sin(Math.toRadians(latitude)
)cosRadiansLatitude
(Math.cos(Math.toRadians(latitude)
)
Sedan när jag söker efter de platser som ligger inom X enheter av latitude
/longitude
i fråga är mitt förberedda uttalande följande:
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
Där YYYY
=3965 ger dig avstånd i miles eller YYYY
=6367 kan användas för avstånd i km.
Slutligen har jag använt maximumSearchLatitude
/ maximumSearchLongitude
/ minimumSearchLongitude
/ maximumSearchLongitude
parametrar för att utesluta majoriteten av poängen från resultatuppsättningen innan databasen måste utföra några beräkningar. Du kanske behöver detta eller inte. Om du använder detta är det upp till dig vilka värden du väljer för dessa parametrar, eftersom det beror på vad du söker.
Uppenbarligen kommer det att krävas kloka tillämpningar av index i databasen.
Fördelen med att använda detta tillvägagångssätt är att informationen som aldrig ändras men som behövs varje gång bara beräknas en gång, medan man beräknar värdena för radiansLongitude
, sinRadiansLatitude
, cosRadiansLatitude
för varje rad varje gång du gör en sökning kommer att bli väldigt dyrt väldigt snabbt.
Det andra alternativet är att använda ett geospatialt index , vilket innebär att allt detta hanteras åt dig av databasen. Jag vet dock inte hur bra Hibernate integrerar med det.
Ansvarsfriskrivning:det var länge sedan jag tittade på det här, och jag är ingen GIS-expert!