地理空间
了解如何在 Redis 中使用地理空间字段并执行地理空间查询
Redis Query Engine 支持地理空间数据。此功能允许您将地理位置和几何形状存储在 JSON 对象的字段中。
您可以索引这些字段,并使用查询按其位置或其形状与其他形状的关系查找对象。例如,如果您添加一组商店的位置,您可以找到用户位置 5 公里范围内的所有商店,或确定哪些商店位于特定城镇的边界内。
Redis 使用坐标点表示地理空间位置。您可以存储单个点,但也可以使用一组点来定义多边形形状(例如,城镇的形状)。您可以查询点和形状之间的几种类型的交互,例如点是否位于形状内或两个形状是否重叠。
Redis 可以将坐标解释为地理经纬度,也可以解释为平面上的笛卡尔坐标。地理坐标非常适合大型真实世界位置和区域(例如城镇和国家)。笛卡尔坐标更适合较小区域(例如建筑物中的房间)或游戏、模拟和其他人工场景。
存储地理空间数据
Redis 支持两种不同的地理空间数据模式类型
-
GEO
:这使用一种简单格式,其中单个地理空间点被指定为数字经纬度对。 -
GEOSHAPE
:Redis 开源版在 v7.2 及更高版本中也支持GEOSHAPE
索引。这使用了Well-Known Text (WKT)格式的一个子集,使用地理坐标或笛卡尔坐标指定点和多边形。GEOSHAPE
字段支持比GEO
更高级的查询,例如检查一个形状是否重叠或包含另一个形状。
下面几节将更详细地描述这些模式类型。
GEO
GEO
索引允许您将地理空间数据表示为包含经纬度对的字符串(例如,“-104.991531, 39.742043”)或这些字符串的 JSON 数组。请注意,经度值在字符串中排在前面。
例如,您可以将下面显示的 JSON 对象的 location
字段索引为 GEO
{
"description": "Navy Blue Slippers",
"price": 45.99,
"city": "Denver",
"location": "-104.991531, 39.742043"
}
{
"description": "Bright Red Boots",
"price": 185.75,
"city": "Various",
"location": [
"-104.991531, 39.742043",
"-105.0618814,40.5150098"
]
}
GEO
字段只允许基本的点和半径查询。例如,下面的查询会查找距离科罗拉多斯普林斯(经度=-104.800644,纬度=38.846127)100 英里半径范围内的产品。
FT.SEARCH productidx '@location:[-104.800644 38.846127 100 mi]'
有关可用查询选项的更多信息,请参阅地理空间查询;有关索引 GEO
字段的示例,请参阅地理空间索引。
GEOSHAPE
索引为 GEOSHAPE
的字段支持来自Well-Known Text几何表示法的 POINT
和 POLYGON
原语。POINT
原语以类似于 GEO
字段的方式定义单个点。下面显示的示例 JSON 对象的 geom
字段指定了一个点(以笛卡尔坐标表示,使用标准的 x,y 顺序)
{
"name": "Purple Point",
"geom": "POINT (2 2)"
}
POLYGON
原语可以使用一系列点来近似任何形状的轮廓。按它们围绕形状出现的顺序(顺时针或逆时针)指定角点坐标,并通过使最后一个坐标与第一个坐标完全相同来确保形状“闭合”。
请注意,POLYGON
要求坐标列表周围有双层括号。这是因为您可以指定额外的形状作为逗号分隔列表,以定义封闭多边形内的“孔洞”。这些孔洞的绕线顺序必须与外部多边形相反(因此,如果外部多边形使用顺时针绕线顺序,则孔洞必须使用逆时针顺序)。下面显示的示例 JSON 对象的 geom
字段指定了一个使用顺时针绕线顺序的笛卡尔坐标正方形
{
"name": "Green Square",
"geom": "POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))"
}
以下示例定义了一个 POINT
原语和三个 POLYGON
原语,如下面的图像所示
POINT (2 2)
POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1))
POLYGON ((2 2.5, 2 3.5, 3.5 3.5, 3.5 2.5, 2 2.5))
POLYGON ((3.5 1, 3.75 2, 4 1, 3.5 1))

您可以针对地理空间索引运行各种类型的查询。例如,下面的查询返回位于绿色正方形边界内的一个原语(来自上面的示例),但省略了正方形本身
> 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\"]"
您可以与 GEOSHAPE
字段一起使用的四种查询操作
WITHIN
:查找完全位于您在查询中指定的封闭形状内的点或形状。CONTAINS
:查找完全包含指定点或形状的形状。INTERSECTS
:查找其边界与另一个指定形状重叠的形状。DISJOINT
:查找其边界与另一个指定形状不重叠的形状。
有关这些查询类型的更多信息,请参阅地理空间查询;有关索引 GEOSHAPE
字段的示例,请参阅地理空间索引。
地理坐标的局限性
地球实际上更像一个椭球体,而不是一个完美的球体。Redis Query Engine 使用的球面坐标系是地球形状的一个近似,但不完全精确。对于大多数实际使用的地理空间查询,这种近似效果很好,但如果您需要非常精确的位置数据(例如,在紧急响应系统中跟踪船只的 GPS 位置),则不应依赖它。