博主信息
JiaJieChen
博文
67
粉丝
3
评论
5
访问量
47251
积分:0
P豆:136

Redis6+PHP:实现根据经纬度计算出附近门店距离

2021年10月13日 11:59:21阅读数:358博客 / JiaJieChen/ PHP

一. 开始介绍: Redis GEO

1.Redis GEO 主要用于存储地理位置信息,并对存储的信息进行操作,该功能在 Redis 3.2 版本新增。

Redis GEO 操作方法
geoadd 添加地理位置的坐标
geopos 获取地理位置的坐标
geodist 计算两个位置之间的距离
georadius 根据用户给定的经纬度坐标来获取指定范围内的地理位置集合
georadiusbymember 根据储存在位置集合里面的某个地点获取指定范围内的地理位置集合
geohash 返回一个或多个位置对象的 geohash 值

2.geoadd

geoadd 用于存储指定的地理空间位置,可以将一个或多个经度(longitude)、纬度(latitude)、位置名称(member)添加到指定的 key 中。

3.geopos

geopos 用于从给定的 key 里返回所有指定名称(member)的位置(经度和纬度),不存在的返回 nil。

4.geodist

geodist 用于返回两个给定位置之间的距离。
  1. 最后一个距离单位参数说明:
  2. m :米,默认单位。
  3. km :千米。
  4. mi :英里。
  5. ft :英尺。

5.georadius

georadius 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
  1. m :米,默认单位。
  2. km :千米。
  3. mi :英里。
  4. ft :英尺。
  5. WITHDIST: 在返回位置元素的同时, 将位置元素与中心之间的距离也一并返回。
  6. WITHCOORD: 将位置元素的经度和维度也一并返回。
  7. WITHHASH: 52 位有符号整数的形式, 返回位置元素经过原始 geohash 编码的有序集合分值。 这个选项主要用于底层应用或者调试, 实际中的作用并不大。
  8. COUNT 限定返回的记录数。
  9. ASC: 查找结果根据距离从近到远排序。
  10. DESC: 查找结果根据从远到近排序。

二. Redis6 + PHP 实现附近门店思路

1.首先在项目后台创建店铺的时候,一定要接通百度地图api,返回相对输入店铺地址的经纬度,保存到数据库后才能实现,没有经纬度无法实现 本人用的是laravel框架~~

  • 接下来是测试数据,如果对读者们有帮助,可以在实际项目中更具自己的思路加强改进~
  • 如果之前创建店铺的时候保存了经纬度,这个数据可以在数据库中读取,id是门店的id,longitude 经度,latitude纬度

  • 如果仔细的读者应该发现了,在这里用的语法是上文介绍过的,在这里只是把名称换成了店铺id,后面比较好和门店进行绑定

  • 可以看到redis库中已经有我们填写的测试数据了,接下来我们结合上文所说到的georadius方法进行取值

  • 这里使用的是asc升序排序,还有desc降序排序,一般附近门店第一个显示的是最近门店,所以用asc升序排序,单位是km 比较好查询

  • 显示的是km单位,把数据拿到后可以 *1000 改成m单位,更具自己的项目需求进行改变

  • 在这里遍历用店铺id做为数组的key

  • 在这将门店距离数据和门店信息数据组合

  • 最后组合成的数据,已经可以在前端小程序中渲染附近门店距离啦,这只是测试数据哦,真实数据要更具自己项目数据进行结合 对读者有帮助的话 帮我点个赞哦 期待留言~~

  • 成品效果哦~~

(ps: 最后可以设防,读取数据库门店信息条数和redis 储存的门店经纬度数据总数 进行对比,如果一致,则直接读取redis数据,否则重新查询数据库,将数据重新赋值给redis,可以减少数据库io查询)

代码块

  1. //模拟门店 id 经度 纬度
  2. $store_location = array(
  3. 0 => array(
  4. 'id' => 1,
  5. 'longitude' => '113.956843',
  6. 'latitude' => '22.575094',
  7. ),
  8. 1 => array(
  9. 'id' => 2,
  10. 'longitude' => '113.957746',
  11. 'latitude' => '22.574877',
  12. ),
  13. 2 => array(
  14. 'id' => 3,
  15. 'longitude' => '113.957036',
  16. 'latitude' => '22.575545',
  17. ),
  18. );
  19. //遍历测试数据 循环在redis 插入 经纬度
  20. foreach ($store_location as $K => $item) {
  21. Redis::GeoAdd('store_location', $item['longitude'], $item['latitude'], $item['id']);
  22. }
  23. //在这里经纬度是写死的,在实际项目中这里传进来的经纬度是更具用户授权定位信息之后拿到的经纬度
  24. $positions = Redis::GeoRadius('store_location', 113.955964, 22.574741, 1000, 'km', 'WITHDIST', 'asc');
  25. //在这里遍历用店铺id做为数组key
  26. $positions_container = [];
  27. foreach ($positions as $k => $v) {
  28. $positions_container[$v[0]] = $v;
  29. }
  30. //这里是门店信息测试数据,读者可以更具项目数据进行读取
  31. $stores = array(
  32. 0 => array(
  33. 'id' => 1,
  34. 'name' => 'ck',
  35. ),
  36. 1 => array(
  37. 'id' => 2,
  38. 'name' => 'myj',
  39. ),
  40. 2 => array(
  41. 'id' => 3,
  42. 'name' => 'tyb',
  43. ),
  44. );
  45. //门店信息容器
  46. $store_info = [];
  47. foreach ($stores as $k => $v) { //遍历门店信息数据
  48. foreach ($positions_container as $kk => $vv) { //遍历相对距离位置
  49. //如果数组key等于门店信息id 则把数据重新赋值给门店信息容器 store_info
  50. if ($kk = $v['id']) {
  51. $store_info[$kk]['id'] = $v['id'];
  52. $store_info[$kk]['name'] = $v['name'];
  53. $store_info[$kk]['apart'] = ($positions_container[$kk][1] * 1) * 1000;
  54. }
  55. }
  56. }
  57. //取出门店距离数组列
  58. $column = array_column($store_info, 'apart');
  59. //更具距离进行升序排序
  60. array_multisort($column, SORT_ASC, $store_info);
  61. dd($store_info);

版权申明:本博文版权归博主所有,转载请注明地址!如有侵权、违法,请联系admin@php.cn举报处理!

全部评论

文明上网理性发言,请遵守新闻评论服务协议

条评论