Redis GEO 快速上手:命令解读与 Spring Data Redis 实战
目录什么是GEO常用命令GEOADD 添加1.原生操作命令2.Java APIGEODIST 测算距离1.原生操作命令2.Java APIGEOHASH 获取坐标整数1.原生操作命令2.Java APIGEOPOS1.原生操作命令2.Java APIGEOSEARCH1.原生操作命令2.Java API删除1.原生操作命令2.Java API使用场景前置介绍Redis 版本 6.2.0org.springframework.data.redis 2.7.18官方文档https://redis.io/docs/latest/commands/geoadd/什么是GEOGEOGeographical地理索引结构本质上是一个有序集合Sorted Set。其核心思想是将地理位置信息转换为一个整数并将这个整数作为分数score存储在有序集合中。这样物理位置上相近的点其对应的整数分数也会非常接近从而实现了基于地理位置的高效索引和查询。常用命令GEOADD1. 原生操作命令GEOADD 键经度longitude维度latitude 名称...GEOADD key [NX | XX] [CH] longitude latitude member [longitude latitude member ...]key包含地理空间索引的键名称已排序集合longitude 经度latitude 纬度member 可以理解为地理位置的唯一标识比如城市名NX不要更新已有的元素。总是添加新元素。XX只更新已经存在的元素。永远不要添加元素。CHchanged的缩写意思是“有多少个地点被我动过”新增的、发生改变的老成员如果新加的成员的经纬度与已存在的相同那么不会计入返回值默认情况、NX返回新增的地点个数XX被改动的老元素的个数CH新增老元素变动的个数工作原理Redis 不是直接把经纬度两个小数存起来而是把它转换成一个52 位的整数geohash。怎么转的呢把地球想象成一张大网格经度和纬度分别用一串二进制来定位然后像洗牌一样把两串二进制交错插在一起最后得到一个整数。这个整数就代表了地球上的一个小方块。2.Java API// 方法一Geolocation Long add(K key, Point point, M member); // 方法二Map 批量添加 Long add(K key, MapM, Point memberCoordinateMap); // 方法三默认方法 Long add(K key, RedisGeoCommands.GeoLocationM location); // 方法四IterableGeoLocationM // 表示一个可以遍历的 GeoLocation 对象列表。 Long add(K key, IterableGeoLocationM locations);Point点位对象public class Point implements Serializable { private static final long serialVersionUID 3583151228933783558L; private final double x; private final double y; .... }GeoLocationT成员唯一标识、点位对象Pointpublic GeoLocation(T name, Point point) { super(name, point); }GEODISTdist通常作为distance距离的缩写所以GEODIST可以理解为返回由排序集合表示的地理空间索引中两个成员之间的距离。1.原生操作命令GEODIST key member1 member2 [M | KM | FT | MI若缺少其中一个或两个成员GEODIST会返回nullm: 米 (meters)km: 千米 (kilometers)ft: 英尺 (feet)mi: 英里 (miles)2.Java API// 方法一默认方法 带有默认单位 米 Distance distance(K key, M member1, M member2); // 方法二可以指定手动距离单位 Distance distance(K key, M member1, M member2, Metric metric);GEOHASHGeohash 操作的本质是一种把二维经纬度“压缩”成一维整数52 位的编码算法。不是直接存入经纬度比如 116.38, 39.90而是算出hash整数存储并当作有序集合的分数返回的哈希字符串具有以下特性可以通过去除右侧字符来缩短。它们会失去精度但仍指向同一区域。具有相似前缀的字符串会在附近但相反情况并非成立也有可能具有不同前缀的字符串也在附近1.原生操作命令GEOHASH key [member [member2.Java APIListString hash(K key, M... members);GEOPOSpos 是英语单词 position 的常见缩写在redis中表示指定成员存储的经纬度1.原生操作命令GEOPOS key [member [member ...]]2.Java APIListPoint position(K key, M... members);GEOSEARCHGEORADIUS在Redis6.2.0之后就被弃用了我们来学新的GEOSEARCH1.原生操作命令GEOSEARCH key FROMMEMBER member | FROMLONLAT longitude latitude BYRADIUS radius 单位 | BYBOX width height 单位 [ASC | DESC] [COUNT count [ANY]] [WITHCOORD] [WITHDIST] [WITHHASH]中心点FROMMEMBER member从现有的元素的位置为中心进行搜索FROMLONLAT longitude latitude以指定坐标为中心形状BYRADIUS radius 单位指定半径的圆圈内BYBOX width height 单位指定长宽的矩形内排序ASC | DESC追加返回值WITHCOORD额外返回每个匹配坐标的经度和纬度。WITHDIST额外返回每个匹配坐标距离中心的距离单位与半径相同。WITHHASH额外返回每个匹配坐标的哈希字符串2.Java APIGeoResultsRedisGeoCommands.GeoLocationM search(K key, Circle within); GeoResultsRedisGeoCommands.GeoLocationM search(K key, GeoReferenceM reference, Distance radius); GeoResultsRedisGeoCommands.GeoLocationM search(K key, GeoReferenceM reference, Distance radius, RedisGeoCommands.GeoSearchCommandArgs args); GeoResultsRedisGeoCommands.GeoLocationM search(K key, GeoReferenceM reference, BoundingBox boundingBox); GeoResultsRedisGeoCommands.GeoLocationM search(K key, GeoReferenceM reference, BoundingBox boundingBox, RedisGeoCommands.GeoSearchCommandArgs args); GeoResultsRedisGeoCommands.GeoLocationM search(K key, GeoReferenceM reference, GeoShape geoPredicate, RedisGeoCommands.GeoSearchCommandArgs args);Distance 半径Circle Point中心点坐标、DistanceGeoReferenceM中心点抽象类fromCoordinate以经纬度坐标为中心fromMember以集合中已有的一个成员为中心GeoSearchCommandArgs 设置额外的查询参数limit()sort(Sort.Direction.ASC/DESC) 、sortAscending 、sortDescendingincludeCoordinates返回经纬度includeDistance返回中心点间距返回值GeoResultsGeoLocationM包含averageDistance平局距离List? extends GeoResultT results“这是 GeoResult 或它子类的列表”不能add只能getPECS原则Producer Extends Consumer SuperProducer生产者你只从容器里 “取” 数据容器是给你提供数据的 —— 用? extends。Consumer消费者你只往容器里 “放” 数据 —— 用? super。删除注意没有GEODEL命令因为你可以用ZREM来移除元素。地理索引结构只是一个排序的集合。1.原生操作命令ZREM key member [member ...]2.Java APILong remove(K key, M... members);使用场景附近的人测算得到GeoHash只比较前缀相同的人大概率就在几公里内可以减少计算量派单匹配司机或骑手持续上报实时位置服务端将其编码为Geohash并持久化。顾客下单时系统先利用Geohash前缀快速圈定附近的候选服务者粗筛再对候选集逐一计算精确距离最终选出距离最近或综合评分最高的人选精排完成高效匹配。、打卡Check-in任何“到达指定位置才能完成操作”的需求本质上都是一次“人在哪里”的验证。将打卡点坐标存入 Redis GEO用户发起打卡时服务端以打卡点为中心、允许误差为半径用GEOSEARCH判断用户当前位置是否在圈内。圈内则打卡成功圈外则拒绝。