java 實現微信搜索附近人功能

最近給andorid作後臺查詢數據功能,有一個需求是模仿微信的查找附近人功能。 數據庫中存儲每一個用戶的經緯度信息及用戶信息,經過當前用戶傳遞過來的經緯度查詢這個用戶半徑N千米之內的用戶信息。   html

數據庫表結構:java

表信息android

表名 Mobile_Usergit

mu_id 自增,主鍵sql

mu_u_id 用戶表的ID 外鍵數據庫

mu_longitud 精度json

mu_latitude 緯度 (還有其餘的一些信息,這裏就列舉4個字段足矣)數組

首先須要一個方法,是把傳遞過來的經緯度按照半徑N千米擴散,找出距離中心經緯度N千米的上下左右經緯度值。效果如圖微信


尷尬 隨手畫的  勿噴
框架


以中心生成經緯度時 正上方和正下方的精度是不變的,只有緯度變化。 生成左右時道理同樣,只有精度變化,緯度是不變的。

因此只須要生成上下的緯度,左右的精度就能夠了。

參考了網上的文章,http://digdeeply.info/archives/06152067.html 這篇文章是用PHP實現的經緯度查詢。修改爲java的 代碼以下

/** 
     * 生成以中心點爲中心的四方形經緯度 
     *  
     * @param lat 緯度 
     * @param lon 精度 
     * @param raidus 半徑(以米爲單位) 
     * @return 
     */  
    public static double[] getAround(double lat, double lon, int raidus) {  
  
        Double latitude = lat;  
        Double longitude = lon;  
  
        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 };  
    }

這樣四周的經緯度都已經生成了。    
下一步是查詢數據庫中和四周經緯度匹配的數據。 若是數據量很大的話會很耗時間,並且會很消耗流量。因此須要用到分頁查詢 

代碼以下 

select * from mobile_user 
			where mu_latitude <> 0
			and mu_longitud > #left_lat#
			and mu_longitud < #right_lat#
			and mu_latitude > #down_lon#
			and mu_latitude < #top_lon#
			and mu_u_id <> #uid#
			order by ACOS(SIN((#lat# * 3.1415) / 180 ) * SIN((mu_latitude * 3.1415) / 180 ) 
			+COS((#lat# * 3.1415) / 180 ) * COS((mu_latitude * 3.1415) / 180 ) 
			*COS((#lon# * 3.1415) / 180 - (mu_longitud * 3.1415) / 180 ) ) 
			* 6380 asc limit #start#,#end#

我用的是ibatis框架,sql裏以#開始並結束的 是我傳遞過來的參數。  sql語句計算了每條數據和中心經緯度的距離而且以最近進行排序。  sql語句是根據下面的方法演變而來
方法是計算兩個經緯度之間的直線距離。

/** 
     * 計算中心經緯度與目標經緯度的距離(米) 
     *  
     * @param centerLon 
     *            中心精度 
     * @param centerLan 
     *            中心緯度 
     * @param targetLon 
     *            須要計算的精度 
     * @param targetLan 
     *            須要計算的緯度 
     * @return 米 
     */  
    private static double distance(double centerLon, double centerLat, double targetLon, double targetLat) {  
  
        double jl_jd = 102834.74258026089786013677476285;// 每經度單位米;  
        double jl_wd = 111712.69150641055729984301412873;// 每緯度單位米;  
        double b = Math.abs((centerLat - targetLat) * jl_jd);  
        double a = Math.abs((centerLon - targetLon) * jl_wd);  
        return Math.sqrt((a * a + b * b));  
    }

這樣既實現了分頁處理,又實現了每條數據的經緯度與中心經緯度的直線距離(以米爲單位)。   
最後就是組成json數組返回給android使用了。  
作個筆記,歡迎補充。

思考:

數據量大了,須要按照經緯度進行分表

鑑於一些網站採集本blog的文章,  本站原創。  http://blog.csdn.net/qq7342272   轉載請註明出處。

相關文章
相關標籤/搜索