根据指定坐标来找出指定距离内的其他坐标(已存在)怎么做?

RT,根据app获取到用户坐标后,将其保存到数据库内,然后根据此坐标搜索表内其他用户,找出与其相近的人。
比如500米之内的用户,用处是能返回给该用户附近的人用户列表

目前想到两个方法,但一个觉得太笨了,耗费资源,另一个貌似不太靠谱:

1.每次遍历库内所有用户,然后与当前用户比对,计算坐标距离(当然这不现实,可以将其分组吧,每次给每个用户一个既定范围,例如该用户在朝阳区西北方向,我在自己地图模型(概念上)里将此区定为CYXB1区,并存入数据库,找附近用户只需要搜索自定区域即可,缺点:不能以用户为圆心画半径去搜索附近的人)

2.根据坐标前N位,或前N位相邻的值 模糊查询,
例如:当前坐标 123.456,456.123
如此在数据库查询 select * from users where x like "{123.4}%" and y like "{456.1}%"; #x代表坐标x轴,y同理

请教一下各位有没有好的解决方法,谢谢

阅读 5.5k
4 个回答

GeoHash,Redis直接支持,快速存储和查询都搞定了,最高0.5%的错误率。

插入用户的坐标:

GEOADD users 13.361389 38.115556 user1
GEOADD users 13.361389 38.115566 user2
...

查里user1半径500米的用户:

GEORADIUSBYMEMBER users user1 500 m

更好的是GEORADIUSBYMEMBER加WITHDIST还能得到用户间距离。

给一个思路,既然我们知道了用户当前位置的经纬度,又知道我们将要搜索的范围,我们可不可以计算出一个范围 ?也就是说,根据一个中心点和半径,计算出符合条件的经纬度的最大值和最小值 。然后sql语句 查处这个范围点用户就可以了

楼上的方案是可行的,但还要进一步优化。
因为如果用户是不停移动的话那岂不是要不停计算经纬度最大值和最小值,然后再根据这些值去数据库里搜索,用户数多的话对服务器的压力不可谓不大呀
所以我觉得应该设定一个活动范围值(要小但不能太小),我们把整个世界地图按这个值划分为一个一个的正方形(对每个方形编个编号),事先将这些方形的上下边纬度和左右边经度存储于数据库中,然后根据方形的中心按设定的距离值(必须能整除活动范围值)计算出周围的正方形编号存储于数据库中。
这样子当有一个用户上线有经纬度时根据它的经纬度计算所处的方形,然后根据之前事先已经存储该方形的周围的方形来获取他周围的用户。同时获取方形上下左右边经纬度和方形编号存储于app,当用户移动不超过这个范围就不用重新获取所在方形,只需要请求方形中的其他用户以及周围方形的其他用户。

用户表

用户编号 方形编号

方形表

方形编号 方形上下左右边经纬度 方形周围方形编号

新手上路,请多包涵

/**

 * 根据一个给定经纬度的点,进行附近地点查询
 * 获取周围坐标
 * @param double $lng
 * @param double $lat
 * @param real $distance
 * @return multitype:multitype:number
 */
public function returnSquarePoint($lng, $lat,$distance = 0.5)
{
    $earthRadius = 6378138;
    $dlng =  2 * asin(sin($distance / (2 * $earthRadius)) / cos(deg2rad($lat)));
    $dlng = rad2deg($dlng);
    $dlat = $distance/$earthRadius;
    $dlat = rad2deg($dlat);
    return array(
        'left-top'=>array('lat'=>$lat + $dlat,'lng'=>$lng-$dlng),
        'right-top'=>array('lat'=>$lat + $dlat, 'lng'=>$lng + $dlng),
        'left-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng - $dlng),
        'right-bottom'=>array('lat'=>$lat - $dlat, 'lng'=>$lng + $dlng)
    );
}

传个坐标进去范围范围
$wherefind['lat']['between']=array($around['right-bottom']['lat'],$around['left-top']['lat']);
                        $wherefind['lng']['between']=array($around['left-top']['lng'],$around['right-bottom']['lng']);
                        然后用范围搜索就可以了
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题