dot 速度的未来即将在您所在的城市举行活动。

加入我们在 Redis 发布活动

GeoBike 第二部分:查询数据

索引数据

之前的文章中,我们使用 Redis 构建了位置感知应用程序的后端,并讨论了如何使用 Python 程序从 通用自行车共享提要规范 (GBFS) 数据提要加载数据,并存储有关在世界各地运营的自行车共享系统的的信息。我们的程序解析了提要中的 JSON 结构化数据,以将有关每个站点的元数据存储在 Redis 中,然后使用 Redis 的 地理空间数据结构对每个站点的地理位置进行索引。

我们的索引和解析程序使用 ${system_id}:station:${station_id} 形式的结构化键将共享站点的元数据加载到 Redis 中,其中 system_id 和 station_id 是 GBFS 数据中指定的唯一标识符。特定共享系统中所有站点的地理空间位置索引使用 ${system_id}:stations:location 键存储。

现在我们已经构建了一个共享站点的后端数据库,并用位置信息对其进行了索引,我们可以使用这些数据来查找位于用户当前位置附近的共享站点。

获取用户的位置

构建应用程序的下一步是确定用户当前的位置。大多数应用程序通过操作系统提供的内置服务来实现此目的。操作系统可以使用设备内置的 GPS 硬件或根据设备可用的 Wi-Fi 网络进行近似来为应用程序提供位置。

在 Apple 设备上,您可以使用 CoreLocation 查找用户当前的位置,CoreLocation 可在所有 Apple 设备 SDK 中使用。如果您正在使用我们的代码进行实验,并想在您的 Mac OS X 笔记本电脑上试用它,您可以下载并构建 whereami 工具,该工具使用 CoreLocation 来估计您的计算机当前的经度和纬度。

查找站点

在我们找到用户当前的位置后,我们想要找到附近的自行车共享站点。使用 Redis 的地理空间函数,我们可以查找在给定距离内我们当前坐标的站点。让我们以使用 Redis CLI 的示例来逐步了解这一点。

假设我在第五大道上的苹果商店,我要去西 37 街的 Mood 与我的朋友 Swatch 会合。我可以坐出租车或地铁,但我更喜欢骑自行车。附近有没有自行车共享站点,我可以借一辆自行车去旅行?

苹果商店位于 40.76384, -73.97297。我们可以在我们创建的第一个帖子中作为地图叠加层的一部分,在商店周围画一个 500 英尺的半径(蓝色),可以看到两个自行车共享站点 - 大军广场和中央公园南,以及东 58 街和麦迪逊 - 位于该半径内。

使用 Redis GEORADIUS 命令,我可以通过对 Redis 发出以下命令来查询我们为纽约市系统加载的索引,以查找半径为 500 英尺内的站点

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 命令可用于从地理哈希中获取给定元素的坐标。例如,如果我知道在西 38 街和第八大道的某个地方有一个自行车共享站点,并且它的 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)。