• 解决方案-LBS用户位置Redis-GEO附近人/店铺


    在这里插入图片描述
    在这里插入图片描述

    windows安装

    Ruoyi-SpringCloud版本-2.安装redis服务端和客户端-win7

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    附近人列表功能

    方案 优势 缺点
    Mysql外接正方形 逻辑清晰,实现简单,支持多条件筛选 效率较低,不适合大数据量,不支持按距离排序
    Mysql+Geohash 借助索引有效提高效率,支持多条件筛选 不支持按距离排序,存在数据库瓶颈
    Redis+Geohash 效率高,集成便捷,支持距离排序 不适合复杂对象存储,不支持多条件查询

    mysql

    轻量级  1w 以内 
    
    经纬度  --->  四个临界点
    
    • 1
    • 2
    • 3

    redis GEO

    GEO 就是 Geolocation 的简写形式,代表地理坐标。

    Redis 在 3.2 版本中加入了对 GEO 的支持,允许存储地理坐标信息,帮助我们根据经纬度来检索数据。

    SRANDMEMBER

    $data = $redis->rawCommand(‘zrangebyscore’, ‘locations’, rand(0, 100), rand(100, 200), ‘WITHSCORES’, ‘LIMIT’, 0, 10);

    zScore是否存在

    ZREM 删除原有成员

            $shop_id = $this->id;
            // 连接Redis
    //        var_dump($shop_id);
            $redis = Cache::store('redis')->handler();
    
            // 查询指定ID的成员是否存在于有序集合中
            $score = $redis->zScore('xxx', $xxx_id);
    
            if ($score === false) {
       
                // 如果成员不存在,则执行GEOADD命令插入数据
                $redis->rawCommand('GEOADD', 'shoper', $data['xxx'], $data['xxx'], $shop_id);
            } else {
       
                // 如果成员已经存在,则先使用ZREM命令删除原有成员,然后再执行GEOADD命令插入新的位置信息
                $redis->rawCommand('ZREM', 'xxx', $xx_id);
                $redis->rawCommand('GEOADD', 'xxx', $data['xxx'], $data['xxx'], $shop_id);
            }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    zrangebyscore

    在 PHP 代码中使用 Redis 的 ZRANGEBYSCORE 命令来获取使用 GEOADD 存储的地理位置数据时,以下是各个参数的含义和示例说明:
    
    key: 要操作的有序集合的键名,这里是用于存储地理位置信息的键名。
    min: 包含的最小经度/纬度值。在地理位置存储中,通常将经度和纬度作为分数存储在有序集合中,因此这里的 min 表示最小的经度或纬度值。
    max: 包含的最大经度/纬度值。与 min 类似,这里的 max 表示最大的经度或纬度值。
    WITHSCORES: 可选参数,如果指定该参数,返回结果将包括成员和对应的分数。
    假设我们有一个地理位置数据存储在 Redis 中,键名为 "locations",通过 GEOADD 命令添加了一些地点的经纬度信息:
    
    php
    $redis->geoadd('locations', 116.397128, 39.916527, 'Beijing');
    $redis->geoadd('locations', 121.472644, 31.231706, 'Shanghai');
    $redis->geoadd('locations', 113.264434, 23.129162, 'Guangzhou');
    现在我们想要从 "locations" 中获取经度范围在 110120 之间,纬度范围在 2040 之间的地点,可以使用 ZRANGEBYSCORE 命令:
    
    php
    $min_longitude = 110;
    $max_longitude = 120;
    $min_latitude = 20;
    $max_latitude = 40;
    $locations = $redis->zrangebyscore('locations', $min_longitude, $max_longitude, ['withscores' => true]);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    GEOADD 将指定的地理空间位置 经度纬度 名称 存储到指定key

    1、GEOADD:添加一个地理空间信息,包含:经度(longitude)、纬度(latitude)、值(member)。
    键名、经度、纬度和成员名称
    geoadd g1 116.378248 39.865275 bjnz 116.42803 39.903738 bjz 116.322287 39.893729 bjxz
    在这里插入图片描述
    2、GEODIST:计算指定的两个点之间的距离并返回。
    在这里插入图片描述
    3、GEOHASH:将指定 member 的坐标转为 hash 字符串形式并返回.
    geohash g1 bjz
    在这里插入图片描述
    4、GEOPOS:返回指定member的坐标

    在这里插入图片描述
    5、GEORADIUS:指定圆心、半径,找到该圆内包含的所有 member,并按照与圆心之间的距离排序后返回。(6.2 以后已废弃)

    6、GEOSEARCH:在指定范围内搜索 member,
    并按照与指定点之间的距离排序后返回。范围可以是圆形或矩形。(6.2 新功能)。

    在Redis中,GEOSEARCH命令用于在地理位置的有序集合中,根据给定的位置信息搜索符合条件的成员。

    
    
    GEOSEARCH命令的语法如下:
    
    GEOSEARCH key
    参数说明:
    
    key:地理位置的有序集合的key名称。
    
    FROMMEMBER member:从指定成员开始搜索,返回符合条件的成员。
    
    FROMLONLAT longitude latitude:从给定的经度和纬度开始搜索,返回符合条件的成员。
    
    BYRADIUS radius unit:根据指定的半径和单位搜索符合条件的成员。
    
    WITHCOORD:返回成员的经纬度坐标。
    
    WITHDIST:返回成员与中心位置的距离。
    
    WITHHASH:返回成员的地理哈希值。
    
    COUNT count:限制返回的成员数量。
    
    ASC|DESC:指定返回结果的排序方式,默认为升序。
    
    STORE key:将搜索结果存储到指定的键名中。
    
    STOREDIST key:将搜索结果存储到指定的键名中,并返回成员与中心位置的距离。
    
    案例:搜索天安门(116.397904 39.909005)附近10km内的所有火车站,并按照距离升序排序。
    
    geosearch g1 fromlonlat 116.397904 39.909005 byradius 10 km withdist
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    在这里插入图片描述

    
    use think\facade\Cache;
    
    
                // 连接Redis
                $redis = Cache::store('redis')->handler();
    
    // 执行GEOADD命令
                $redis->rawCommand('GEOADD', 'cities', $log, $lat, $data['mobile']);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
     
    服务器  设置成  0.0.0.0
    
    • 1
    • 2

    1、将店铺信息添加到缓存中

    在这里插入图片描述

    GEORADIUS 以给定的经纬度为中心 找出某一半径内元素

    GEORADIUS 命令是 Redis 提供的一个用于地理位置查询的命令,其参数如下:

    1. Key:表示要进行地理位置查询的键名。

    2. Longitude:表示查询的中心点经度。

    3. Latitude:表示查询的中心点纬度。

    4. Radius:表示查询的半径范围(单位由 Unit 参数决定)。

    5. Unit:表示查询的半径单位,可以是 m(米)、km(千米)、mi(英里)或 ft(英尺)。

    6. WITHCOORD:表示在查询结果中返回位置的经纬度坐标。

    7. WITHDIST:表示在查询结果中返回位置与中心点的距离(单位由 Unit 参数决定)。

    8. WITHHASH:表示在查询结果中返回位置的 Geohash 值。

    9. COUNT:表示在查询结果中最多返回的位置数量。

    10. SORTED:表示返回的结果按照距离从近到远排序。

    以上参数都是可选的,使用时可以按需选择。

    // 首先获取数据总数
    $count = $redis->zcard('shoper');
    
    // 随机获取10个
    $random_data = $redis->zRandMember('shoper', 10);
    
    // 输出10个结果
    foreach ($random_data as $id) {
       
        echo $id . "\n";
    }
    
    
    
    // 方法1:insertGetId方法,新增数据并返回主键值使用getLastInsID
    Db::name('user')->insert($data);
    $userId = Db::name('user')->getLastInsID();
    
    
    // 方法2:使用insertGetId方法
    Db::name('user')->insertGetId($data);
    
    
    // 方法3:insert第三个参数设置为true,可以返回插入的主键
    $userId = Db::name('user')->insert($data, false, true);
    
    
    //方法4:第四个参数,设置当前插入标识,然后根据标识查询返回值
    Db::name('user')->insert($data, false, false, 'user_insert_id');
    $userId = Db::name('user')->getLastInsID('user_insert_id');
    
    
    create()
    
    create方法返回当前模型的对象实例,用箭头符号就能获取主键ID
    如果你的自增ID是id的话,获取方法也要变成 $order->id
    
    $order 
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    ES6(1) let 和 const
    浅谈wheel滚轮事件
    【无标题】
    R3F(React Three Fiber)经验篇
    Linux虚拟机共享文件夹不显示问题终极解决方法
    若依前后端分离版获取部门表所有最子级部门并匹配部门名称生成excel
    本人碰到的RN项目的坑
    docker-compose
    学习笔记-算法-9-二叉树-1
    C#面向对象程序设计课程实验二: 实验名称:Windows 窗体程序
  • 原文地址:https://blog.csdn.net/qq_33608000/article/details/133893953