MySql中實現 按經緯度搜索附近的人,並按距離排序的簡單實現
阿新 • • 發佈:2019-01-03
按經緯度搜索附近的人,並按距離排序的簡單實現
這是一種簡單的實現,資料量不大的情況下還是能滿足需求的,寫在這裡做一份記錄。當然也希望有其他更好的方案。
主要思路就是:先以自己的經緯度為中心,計算一定半徑內的方形經緯度邊界,然後用此方形經緯度邊界過濾使用者,並使用一個計算兩點經緯度之間距離的自定義資料庫函式計算距離,然後按計算得到的距離倒序
計算一定半徑內的方形經緯度
long raidus = 10000; //半徑10km
double lat = 23.155778; //當前緯度
double lon = 113.262744; //當前經度
Map<String, Object> param = new HashMap<>();
param.put("lat", lat);
param.put("lon", lon);
private void loadGeoSquare(Map<String, Object> parm, double lat, double lon, long raidus){
Double latitude = lat;
Double longitude = lon;
// 赤道周長24901英里 1609是轉換成米的係數
Double degree = (24901 * 1609) / 360.0;
double raidusMile = raidus;
Double dpmLat = 1 / degree;
Double radiusLat = dpmLat * raidusMile;
Double minLat = latitude - radiusLat;
Double maxLat = latitude + radiusLat;
Double mpdLng = degree * Math.cos(latitude * (Math.PI / 180));
Double dpmLng = 1 / mpdLng;
Double radiusLng = dpmLng * raidusMile;
Double minLng = longitude - radiusLng;
Double maxLng = longitude + radiusLng;
//return new double[] { minLat, minLng, maxLat, maxLng };
parm.put("minLat", minLat);
parm.put("minLng", minLng);
parm.put("maxLat", maxLat);
parm.put("maxLng", maxLng);
}
SQL計算
我用的Mybatis,當然SQL大家應該都能看懂
<select id="queryNearbyPage" resultType="AppUserNearby">
SELECT id, avatar, nickname, sex, birthday, lovecode,
ROUND(lat_lng_distance(#{lat}, #{lon}, lat, lon), 2) AS distance
FROM zan_user zuser
WHERE
<![CDATA[ AND lat > #{minLat} AND lat < #{maxLat} AND lon > #{minLng} AND lon < #{maxLng} ]]>
ORDER BY distance ASC
LIMIT #{rowStart},#{rowEnd}
</select>
其中的 計算兩個經緯度之間距離的 資料庫函式,這裡也貼出來:
CREATE FUNCTION `lat_lng_distance` (lat1 FLOAT, lng1 FLOAT, lat2 FLOAT, lng2 FLOAT)
RETURNS FLOAT
DETERMINISTIC
BEGIN
RETURN 6371 * 2 * ASIN(SQRT(
POWER(SIN((lat1 - abs(lat2)) * pi()/180 / 2),
2) + COS(lat1 * pi()/180 ) * COS(abs(lat2) *
pi()/180) * POWER(SIN((lng1 - lng2) *
pi()/180 / 2), 2) ));
END
--Returns the distance in kilometers, assuming a earth radius of 6,371 km.
總結
以上計算上的數學理論,我沒有深究,也是參看相關資料的。總感覺這種實現方式好搓。