地理空间篇

地理空间索引(Geospatial indexes)为在Redis中管理和使用地理空间数据提供了一种极为高效和简单的方法。您可以添加带有经纬度的唯一项,计算对象之间的距离,并查找某个位置给定半径范围内的成员。

geo-redis

场景

地理空间索引的使用场景都和经纬度有关系,比如附近商家,地点签到和打卡,离我最近的商家等等。

附近商家或服务查询

在位置服务应用中,用户可以根据自己的位置查询附近的商家、餐厅、加油站等服务点,Redis地理空间索引可以存储这些服务点的地理位置信息,并通过半径查询功能快速地找到附近的服务点。


$myPoint = [120.298501, 30.41875];

// 127.0.0.1:6379> geoadd service_points  120.298241 30.420017 "gas:13" 120.297114 30.417817 "restaurant:13" 120.300417 30.417674 "bus:13" 120.299809 30.420898 "school:13"
// (integer) 4
// 添加四个不同的服务点, gas前缀代表加油后面数字是ID,其它的类似。
$redis->geoAdd("service_points",
    120.298241, 30.420017, "gas:13", // 加油站 
    120.297114, 30.417817, "restaurant:13", // 餐厅
    120.300417, 30.417674, "bus:13", // 公交站 
    120.299809, 30.420898, "school:13", // 学校
);

$options = ['WITHDIST'];
// 获取以半径150米内的成员, 这个结果只有加油站
// 127.0.0.1:6379> GEORADIUS service_points 120.298501 30.41875 150 m WITHDIST
// 1) 1) "gas:13"
//   2) "143.0264"
$members = $redis->geoRadius('service_points', $myPoint[0], $myPoint[1], 150, 'm', $options);

// 获取以半径300米内的成员, 可以取全部成员
// 127.0.0.1:6379> GEORADIUS service_points 120.298501 30.41875 300 m WITHDIST
// 1) 1) "restaurant:13"
//    2) "168.7446"
// 2) 1) "gas:13"
//    2) "143.0264"
// 3) 1) "school:13"
//    2) "269.8129"
// 4) 1) "bus:13"
//    2) "219.4646"
$members = $redis->geoRadius('service_points', $myPoint[0], $myPoint[1], 300, 'm', $options);

出租车调度系统

在出租车调度系统中,可以使用Redis地理空间索引来存储出租车和乘客的位置信息,通过空间查询功能快速找到距离最近的出租车,并进行调度。


$options['count'] = 1;
$options[] = 'WITHDIST';
$options[] = 'ASC';
// 取出以myPoint为圆点附近300m的车,只离我最近的一辆
$members = $redis->geoRadius('taxis', $myPoint[0], $myPoint[1], 300, 'm', $options);

地点签到和打卡

在社交网络或移动应用中,用户可以根据自己的位置进行签到和打卡操作,Redis地理空间索引可以存储用户的签到位置,并提供附近的签到点查询功能。

// 比如 用户必须在某个点签到,只需要算出用户和签到点的距离就行了.
$userMember =  'user:1';
$signedPointMember = 'sign:12'
$distance = $redis->geoDist($key, $userMember, $signedPointMember, 'm');
// 距离大于 100 就不能签到
if ($distance > 100) {
    return false;
}
// todo

地理围栏和地理提醒

可以使用Redis地理空间索引来存储地理围栏的位置信息,当用户进入或离开某个围栏区域时触发提醒或事件,例如位置提醒、进出场提醒等。


$redis->geoAdd('area',
    120.298241, 30.420017, "center", // 设置区域中心
 );
 
 $redis->geoAdd('area', 
    120.298241, 31.420017, "user:11", // 更新用户位置
 );
 
 
// 当前用户位置信息变更时就检测与中心的距离
$distance = $redis->geoDist('area', 'user:11', 'center', 'm');
// 比如大于  100米说明就离开了
if ($distance > 100) {
    // todo
} else {
    // todo
}

配送路线规划

在物流配送系统中,可以使用Redis地理空间索引来存储配送点和客户的位置信息,通过空间查询功能快速规划最优的配送路线和顺序。

地理热点分析

可以使用Redis地理空间索引来存储用户的位置信息,通过空间聚合功能进行地理热点分析,了解用户活动的热点区域和趋势。这个功能需要界面上把所有的位置显示在地图上来展示活动区域。

// 这个需要实时更新用户的位置
 $redis->geoAdd('users', 
    120.298241, 31.420017, "user:11", // 更新用户位置
    120.298241, 31.420017, "user:12", // 更新用户位置
    120.298241, 31.420017, "user:13", // 更新用户位置
    120.298241, 31.420017, "user:14", // 更新用户位置
    120.298241, 31.420017, "user:15", // 更新用户位置
 );
 

移动设备定位

在移动应用中,可以使用Redis地理空间索引来存储移动设备的位置信息,实现位置跟踪和定位服务。


$redis->geoAdd('devices',  120.298241, 31.420017, "device_id");
// 获取设备的经纬度
$redis->geoPos('devices', 'device_id');

活动地点推荐

在活动推荐系统中,可以使用Redis地理空间索引来存储活动地点的位置信息,并根据用户的当前位置推荐附近的活动地点。这个类似位置签到可以参考上面代码

协作

如果你有更多的场景使用用例,可以通过github提交pr请求。有问题可以开issue编辑此页面