登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  Redis

Redis GEOSEARCH 怎样按中心点和半径筛选地理成员

来源:17golang原创

时间:2026-10-24 19:00:54 278浏览 收藏

在“查找某个坐标附近的门店、设备或配送点”这类需求里,Redis 的地理数据结构适合先把成员和经纬度放进一个索引,再用 GEOSEARCH 描述查询中心与范围。真正容易写错的地方不是命令名称,而是把经度、纬度顺序、距离单位、排序和数量上限混在一起。

官方地址:https://redis.io/docs/latest/commands/geosearch/

按中心点和半径筛选地理成员时,使用 FROMLONLAT longitude latitude BYRADIUS radius unit;如果需要“最近的若干个”,再加 ASC COUNT n,并用 WITHDIST 返回距离。COUNT n ANY 可以减少寻找足够结果的工作,但不能当作严格的最近排序。

先把地理成员写成可查询索引

GEOSEARCH 查询的是由 GEOADD 写入的地理索引。下面用门店作为示例,key 叫 geoshops,每个成员包含经度、纬度和门店名。经度在前、纬度在后,顺序不要交换。

# 写入三个门店:经度在前,纬度在后,最后一个参数是成员名
redis-cli GEOADD geoshops 116.397128 39.916527 "王府井店" \
  116.407526 39.904030 "前门店" \
  116.447456 39.938840 "东直门店"

# 以指定经纬度为中心,在 5 千米圆形区域内查找成员
redis-cli GEOSEARCH geoshops FROMLONLAT 116.397128 39.916527 \
  BYRADIUS 5 KM ASC WITHDIST WITHCOORD

第一条命令只负责建立索引,第二条命令才负责筛选。一个 key 对应一组地理成员,成员名是返回结果中最容易继续关联业务详情的标识;商品、门店营业状态等信息仍可放在 Hash 或其他 key 中。

GEOADD 地理索引与 GEOSEARCH 半径查询的静态结构说明图
图1:GEOADD 地理成员与 GEOSEARCH 中心点、半径区域的静态关系。

用 FROMLONLAT 和 BYRADIUS 组成圆形查询

命令的关键结构可以拆成三块:geoshops 是索引 key,FROMLONLAT 116.397128 39.916527 给出查询中心,BYRADIUS 5 KM 给出圆形范围。单位可以是米 M、千米 KM、英尺 FT 或英里 MI。

# 使用已有成员作为中心时,改用 FROMMEMBER;它不能和 FROMLONLAT 同时出现
redis-cli GEOSEARCH geoshops FROMMEMBER "王府井店" \
  BYRADIUS 2 KM ASC

# 使用坐标作为中心时,明确半径单位,避免把 5 当成 5 米或 5 千米的歧义
redis-cli GEOSEARCH geoshops FROMLONLAT 116.397128 39.916527 \
  BYRADIUS 5 KM

FROMMEMBER 和 FROMLONLAT 是两种互斥的中心定义方式;BYRADIUS 和 BYBOX 也是互斥的范围定义方式。本文只处理圆形半径筛选,因此不要把矩形范围的宽高参数混进同一条命令。

如果项目仍在使用 GEORADIUS 或 GEORADIUSBYMEMBER,迁移时可以把“中心 + 圆形范围”的表达改成 GEOSEARCH。但迁移的重点是重新核对参数顺序和返回结构,不是简单地替换字符串。

排序、数量和返回字段怎么选

默认返回的是匹配到的成员名。如果业务要展示“离用户最近的 10 家店”,用 ASC COUNT 10 表达“近到远、最多 10 个”,并追加 WITHDIST 让应用直接得到距离。

# 只取距离中心最近的 10 个成员,并返回距离与坐标
redis-cli GEOSEARCH geoshops FROMLONLAT 116.397128 39.916527 \
  BYRADIUS 5 KM ASC COUNT 10 WITHDIST WITHCOORD

DESC 表示从远到近;不写排序时,结果不应被业务当成“最近顺序”。WITHDIST 返回的距离使用 BYRADIUS 中相同的单位,WITHCOORD 则附加每个成员的经度和纬度。如果只需要成员名,不要为了方便解析而盲目开启所有 WITH* 选项。

COUNT 10 ANY 是另一种取舍:服务器找到足够数量后可以更早返回,适合“尽快拿到一批候选”的场景;代价是结果可能不按距离排序。因此,外卖配送、最近门店这类严格依赖距离顺序的需求不要把 ANY 和“最近”同时当成无条件保证。

GEOSEARCH 排序数量和返回字段参数取舍说明图
图2:ASC、COUNT、ANY、WITHDIST 与 WITHCOORD 的参数取舍关系。

把“能查到”与“查得适合业务”分开

这条命令的复杂度会受到筛选区域和区域内成员数量影响。半径越大、成员越密集,候选范围就越大;在大范围查询里,先限制业务允许的半径,再用合理的 COUNT,比无条件返回全部成员更容易控制响应体。

需求建议写法需要注意
查中心点附近全部成员FROMLONLAT ... BYRADIUS ...结果多时要考虑返回体大小
查最近的前 N 个ASC COUNT N WITHDIST不要省略 ASC
尽快拿一批候选COUNT N ANY不能依赖严格距离排序
页面还要显示坐标WITHCOORD调用方要适配嵌套返回结构

官方文档将 GEOSEARCH 标记为 Redis Open Source 6.2.0 起可用,并说明它扩展了旧的圆形查询命令。部署环境如果低于这个版本,先确认命令可用性;不要仅凭客户端方法名判断服务端一定支持。

常见问题

经纬度写反会怎样?

查询中心和写入成员都使用“经度在前、纬度在后”。如果两处顺序不一致,命令仍可能执行,但筛选区域会落在错误位置,排查时要先对照数据来源的字段定义。

为什么加了 COUNT 还是不是最近的?

检查是否写了 ASC,以及是否使用了 ANY。后者允许更快得到足够数量的结果,但结果可能无序;严格最近排序应使用 ASC COUNT N,不要加 ANY。

只想返回成员名,还需要 WITHDIST 吗?

不需要。没有 WITH* 选项时返回成员名;只有页面或后续业务确实需要距离、坐标或 geohash 时,再按需添加对应选项。

总结

Redis GEOSEARCH 的半径筛选可以记成一条组合:先用 GEOADD 建好地理索引,再用 FROMLONLAT 或 FROMMEMBER 定义中心,用 BYRADIUS 定义单位明确的圆形范围;需要最近排序时加 ASC,需要数量控制时加 COUNT,需要距离或坐标时再加 WITHDIST、WITHCOORD。真正的工程判断在于:严格排序与快速候选之间,选择符合业务语义的参数。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>