索引数据
在之前的一篇文章中,我们使用 Redis 构建了一个位置感知应用程序的后端,并且讨论了如何使用 Python 程序从通用自行车共享信息规范 (GBFS) 数据馈送加载数据,并存储有关全球自行车共享系统的信息。我们的程序解析来自馈送的 JSON 结构化数据,以将每个站点的元数据存储在 Redis 中,然后使用 Redis 的地理空间数据结构索引每个站点的位置。
我们的索引和解析程序使用${system_id}:station:${station_id}形式的结构化键将共享站点的元数据加载到 Redis 中,其中 system_id 和 station_id 是 GBFS 数据中指定的唯一标识符。特定共享系统中所有站点的地理空间位置索引使用键${system_id}:stations:location存储。
现在我们已经构建了一个共享站点的后端数据库,并使用位置信息对其进行了索引,我们可以使用这些数据来查找位于用户当前位置附近的共享站点。
获取用户的位置
构建我们的应用程序的下一步是确定用户当前的位置。大多数应用程序通过操作系统提供的内置服务来实现这一点。操作系统可以根据设备内置的 GPS 硬件或从设备的可用 WiFi 网络估算位置来为应用程序提供位置信息。
在 Apple 设备上,您可以使用CoreLocation查找用户当前的位置,该工具在所有 Apple 设备 SDK 中都可用。如果您正在尝试我们的代码并想在您的 Mac OS X 笔记本电脑上试用,您可以下载并构建whereami工具,该工具使用 CoreLocation 来估计您计算机当前的经度和纬度。
查找站点
在我们找到用户当前位置后,我们希望找到附近的任何自行车共享站点。 使用Redis 的地理空间函数,我们可以查找当前坐标给定距离内的站点。让我们通过使用 Redis CLI 的示例来了解这一点。
想象一下,我在第五大道的 Apple Store,我想前往西 37 街的 Mood 与我的好友Swatch会面。我可以乘坐出租车或地铁,但我更喜欢骑自行车。附近是否有任何共享站点可以借一辆自行车出行?
Apple Store 位于 40.76384, -73.97297。我们可以在地图叠加层上以商店为中心绘制一个 500 英尺半径的圆(蓝色),该地图叠加层是我们作为第一篇文章的一部分创建的,并且可以看到两个自行车共享站点 - 大陆军广场和中央公园南以及东 58 街和麦迪逊 - 都在半径范围内。
使用 Redis GEORADIUS 命令,我可以查询我们为 NYC 系统加载的索引,以查找 500 英尺半径内的站点,方法是向 Redis 发出以下命令
127.0.0.1:6379> GEORADIUS NYC:stations:location -73.97297 40.76384 500 ft
1) "NYC:station:3457"
2) "NYC:station:281"
Redis 返回在该半径内找到的两个元素。我们的地理空间索引中的元素是特定站点的元数据的键,因此我们将查找两个站点的名称
127.0.0.1:6379> hget NYC:station:281 name
"Grand Army Plaza & Central Park S"
127.0.0.1:6379> hget NYC:station:3457 name
"E 58 St & Madison Ave"
我们发现这些键对应于我们从上面的地图中识别出的站点。 我们可以向 GEORADIUS 命令添加额外的标志,以获取元素列表、它们的坐标以及它们与我们当前点的距离
127.0.0.1:6379> GEORADIUS NYC:stations:location -73.97297 40.76384 500 ft WITHDIST WITHCOORD ASC
1) 1) "NYC:station:281"
2) "289.1995"
3) 1) "-73.97371262311935425"
2) "40.76439830559216659"
2) 1) "NYC:station:3457"
2) "383.1782"
3) 1) "-73.97209256887435913"
2) "40.76302702144496237"
在查找与这些键关联的名称后,我们可以向用户提供一个排序的站点列表,以便他们可以选择一个位置。 Redis 不提供任何方向或路线功能,因此您需要使用设备操作系统的路线规划功能来为用户绘制从其当前位置到所选自行车站点的路线。
GEORADIUS 函数可以轻松地在您最喜欢的开发框架中的 API 中实现,以向应用程序添加位置功能。
其他查询命令
除了 GEORADIUS 命令之外,Redis 还提供了三个其他命令来从索引中查询数据:GEOPOS、GEODIST 和GEORADIUSBYMEMBER。
GEOPOS 命令可用于从 geohash 中获取给定元素的坐标。例如,如果我知道在 W 38 街和第 8 大道上有一个自行车共享站点,并且其 ID 为 523,那么该站点的元素名称为 NYC:station:523。使用 Redis,我们可以找到该特定站点的经度和纬度
127.0.0.1:6379> GEOPOS NYC:stations:location NYC:station:523
1) 1) "-73.99138301610946655"
2) "40.75466497634030105"
GEODIST 命令提供索引的两个元素之间的距离。如果我想找到大陆军广场和中央公园南的站点与东 58 街和麦迪逊的站点之间的距离,我将发出以下命令
127.0.0.1:6379> GEODIST NYC:stations:location NYC:station:281 NYC:station:3457 ft
"671.4900"
最后,GEORADIUSBYMEMBER 命令类似于 GEORADIUS 命令,但该命令不是采用一组坐标,而是采用索引中另一个成员的名称,并返回以该成员为中心给定半径内的所有成员。要查找大陆军广场和中央公园南 1000 英尺范围内的所有站点,请输入以下内容
127.0.0.1:6379> GEORADIUSBYMEMBER NYC:stations:location NYC:station:281 1000 ft WITHDIST
1) 1) "NYC:station:281"
2) "0.0000"
2) 1) "NYC:station:3132"
2) "793.4223"
3) 1) "NYC:station:2006"
2) "911.9752"
4) 1) "NYC:station:3136"
2) "940.3399"
5) 1) "NYC:station:3457"
2) "671.4900"
Redis 的地理空间索引功能使开发人员可以轻松地将位置感知功能添加到他们的应用程序中。如果您对此帖子有任何疑问,请在 Twitter 上与我联系 (@tague)。