根据经纬度坐标查询最近的门店

1. 直接通过 mysql 查询

DB::table('shop')->selectRaw("id,lon,lat,
  ROUND(ST_DISTANCE(point(lon,lat),point({$lon},{$lat})) /0.0111,2) distance")
  ->orderBy('distance')
  ->first();

2. 查询所有坐标,循环计算距离

/** 获取用户最近的店铺
 * @param $shopList
 * @param $lon
 * @param $lat
 * @return array
 */
function nearestShop($shopList, $lon, $lat){
    $arr = [];
    foreach ($shopList as $key => $shop){
        $arr[$key] = getDistance($lon, $lat, $shop->lon, $shop->lat);
    }
    asort($arr);    //按距离排序
    return $shopList[array_keys($arr)[0]];
}

/** 根据坐标计算距离
 * @param float $lon1
 * @param float $lat1
 * @param float $lon2
 * @param float $lat2
 * @param int $unit 单位 2是公里
 * @param int $decimal 四舍五入小数点后位数
 * @return float
 */
function getDistance($lon1, $lat1, $lon2, $lat2, $unit = 2, $decimal = 2){
    $EARTH_RADIUS = 6371; // 地球半径系数

    //将角度转为狐度
    $radLng1 = deg2rad($lon1);
    $radLat2 = deg2rad($lat2);
    $radLat1 = deg2rad($lat1);
    $radLng2 = deg2rad($lon2);

    $distance = 2 * asin(sqrt(pow(sin(($radLat1-$radLat2) / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin(($radLng1-$radLng2) / 2), 2))) * $EARTH_RADIUS * 1000;

    if ($unit === 2) {
        $distance /= 1000;
    }
    return round($distance, $decimal);
}
php
本作品采用《CC 协议》,转载必须注明作者和本文链接
所幸无碍
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 7

2种方法的效率有测过吗

1个月前 评论
❤seven 1个月前
playmaker

redis GEO不香吗?

1个月前 评论
liaosp 1个月前
Steven1998 1个月前
expectedSelf (楼主) 1个月前

你这每次查询都是全表扫描计算`性能有问题 我用过的2种方法来处理LBS问题

  1. 用mysql自带的geohash来处理,这个可以参考mysql文档,给每个坐标生成一个hash值,然后用索引like去查找,长度越长精度越高,但是不能做到自由的精确查找,有一定误差,可以先筛选再计算
  2. 将坐标和id导入到其他支持空间计算的第三方,比如mongo/redis啥,计算查找出来id,再去mysql查询具体数据
1个月前 评论

这种需求适合用geo hash 实现

1个月前 评论

0.0111 为啥用这个

1个月前 评论
expectedSelf (楼主) 2周前

曾经做过,使用 geohash 方案

2周前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!