一、地理空间索引概览
Redis 支持两种地理空间索引类型:
- GEO:对单个地理坐标点(经度、纬度)建立索引,适合“查找半径内的点”场景。
- 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
四、最佳实践与注意事项
- 选择坐标系:平面 (
FLAT
) 适用于小范围或 XY 逻辑空间;地理球面 (SPHERICAL
) 适合地球经纬度。 - 前缀过滤:使用
PREFIX
限定要索引的 Key 空间,减少不必要索引开销。 - DIALECT 版本:地理形状和高级查询需设
DIALECT 2
。 - 索引与存储分离:对只需返回但不检索的字段可加
NOINDEX
。 - 避免超大形状:对超大多边形做复杂关系运算可能性能开销较高,需根据业务限缩范围或预过滤。
通过 GEO 与 GEOSHAPE 索引,Redis 不仅能满足“附近搜索”的常见需求,还能实现基于区域、碰撞与包含关系的高级空间查询,为地理位置服务、地图应用、室内定位等场景提供坚实支撑。