Redis 地理空间索引实践

发布于:2025-07-04 ⋅ 阅读:(20) ⋅ 点赞:(0)

一、地理空间索引概览

Redis 支持两种地理空间索引类型:

  1. GEO:对单个地理坐标点(经度、纬度)建立索引,适合“查找半径内的点”场景。
  2. GEOSHAPE:通过 WKT(Well-Known Text)格式定义点、线、面等几何体,支持更丰富的空间关系查询(如包含、相交、相离等)。

二、GEO 索引

2.1 创建 GEO 索引

假设你的 JSON 文档中有一字段 location,存放 "lon, lat" 格式的字符串,使用以下命令建立 GEO 索引:

FT.CREATE productidx
  ON JSON
  PREFIX 1 product:
  SCHEMA
    $.location AS location GEO

说明

  • ON JSON:对 JSON 文档建索引;
  • PREFIX 1 product::只索引 key 以 product: 开头的文档;
  • $.location:JSONPath,取文档中 location 字段;
  • AS location GEO:将其映射为属性 location,类型为 GEO。

2.2 插入示例文档

JSON.SET product:46885 $ \
  '{"description":"Navy Blue Slippers","price":45.99,"city":"Denver","location":"-104.991531,39.742043"}'
JSON.SET product:46886 $ \
  '{"description":"Bright Green Socks","price":25.50,"city":"Fort Collins","location":"-105.0618814,40.5150098"}'

新插入的文档会自动同步到索引,无需额外操作。

2.3 半径检索

查找距离科罗拉多斯普林斯(-104.800644,38.846127) 100 英里内的商品:

FT.SEARCH productidx \
  "@location:[-104.800644 38.846127 100 mi]"
  • 如果将半径调至 200 mi,则能同时返回丹佛和柯林斯的文档。

三、GEOSHAPE 索引

3.1 创建 GEOSHAPE 索引

当需要对多边形或更复杂的几何体做检索时,使用 GEOSHAPE。以下示例将坐标系设为平面(Cartesian):

FT.CREATE geomidx
  ON JSON
  PREFIX 1 shape:
  SCHEMA
    $.name AS name TEXT
    $.geom AS geom GEOSHAPE FLAT
  • GEOSHAPE FLAT:指定平面坐标;如需球面地理坐标,改用 GEOSHAPE SPHERICAL

3.2 插入几何体文档

JSON.SET shape:1 $ '{"name":"Green Square","geom":"POLYGON ((1 1,1 3,3 3,3 1,1 1))"}'
JSON.SET shape:2 $ '{"name":"Red Rectangle","geom":"POLYGON ((2 2.5,2 3.5,3.5 3.5,3.5 2.5,2 2.5))"}'
JSON.SET shape:3 $ '{"name":"Blue Triangle","geom":"POLYGON ((3.5 1,3.75 2,4 1,3.5 1))"}'
JSON.SET shape:4 $ '{"name":"Purple Point","geom":"POINT (2 2)"}'

3.3 空间关系查询

3.3.1 WITHIN:点在多边形内

查询所有完全绿色正方形内的几何体(排除自己):

FT.SEARCH geomidx \
  "(-@name:(Green Square) @geom:[WITHIN $qshape])" \
  PARAMS 2 qshape "POLYGON ((1 1,1 3,3 3,3 1,1 1))" \
  RETURN 1 name \
  DIALECT 2

返回:

1) (integer) 1
2) "shape:4"
3) 1) "name"
   2) "[\"Purple Point\"]"
3.3.2 其他空间操作
  • CONTAINS:索引形状完全包含查询形状
  • INTERSECTS:与查询形状有任意交集
  • DISJOINT:与查询形状完全不相交

使用方法示例(需 DIALECT 2):

FT.SEARCH geomidx \
  "@geom:[CONTAINS $poly]" PARAMS 1 poly "POLYGON ((...))" DIALECT 2

四、最佳实践与注意事项

  1. 选择坐标系:平面 (FLAT) 适用于小范围或 XY 逻辑空间;地理球面 (SPHERICAL) 适合地球经纬度。
  2. 前缀过滤:使用 PREFIX 限定要索引的 Key 空间,减少不必要索引开销。
  3. DIALECT 版本:地理形状和高级查询需设 DIALECT 2
  4. 索引与存储分离:对只需返回但不检索的字段可加 NOINDEX
  5. 避免超大形状:对超大多边形做复杂关系运算可能性能开销较高,需根据业务限缩范围或预过滤。

通过 GEO 与 GEOSHAPE 索引,Redis 不仅能满足“附近搜索”的常见需求,还能实现基于区域、碰撞与包含关系的高级空间查询,为地理位置服务、地图应用、室内定位等场景提供坚实支撑。