使用 Redis GEO 储存地理位置
2011 年 9 月 16 日
很多社交网站都提供了与地理位置相关的功能, 比如记录用户自己的位置、获取指定用户的位置, 又或者查找指定范围内的其他用户等等。
在学习了 GEOADD
、 GEOPOS
和 GEODIST
这三个命令之后, 我们同样可以构建出一个具有基本功能的用户地理位置程序, 该程序能够记录用户所在的位置、获取指定用户所在的位置以及计算两个用户之间的直线距离, 具体的实现如代码清单 9-1 所示。
代码清单 9-1 具有基本功能的用户地理位置程序: /geo/location.py
import random USER_LOCATION_KEY = "user_locations" class Location: def __init__(self, client): self.client = client self.key = USER_LOCATION_KEY def pin(self, user, longitude, latitude): """ 记录指定用户的坐标。 """ self.client.geoadd(self.key, longitude, latitude, user) def get(self, user): """ 获取指定用户的坐标。 """ position_list = self.client.geopos(self.key, user) # geopos() 允许用户输入多个位置,然后以列表形式返回各个位置的坐标。 # 因为我们这里只传入了一个位置,所以只需要取出列表的第一个元素即可。 if len(position_list) != 0: return position_list[0] def calculate_distance(self, user_a, user_b): """ 以公里为单位,计算两个用户之间的直线距离。 """ return self.client.geodist(self.key, user_a, user_b, unit="km")
这个程序所做的就是使用 GEOADD
命令把用户的 ID 以及用户所在的经纬度关联起来, 然后使用 GEOPOS
命令去获取用户所在的经纬度, 又或者使用 GEODIST
命令去计算两个用户之间的直线距离。
通过执行以下代码, 我们可以创建出相应的用户位置对象, 并使用它记录 peter 、jack 和 tom 这三个用户的地理位置:
>>> from redis import Redis >>> from location import Location >>> client = Redis(decode_responses=True) >>> location = Location(client) >>> location.pin("peter", 113.20996731519699, 23.593675019671288) >>> location.pin("jack", 113.22784155607224, 23.125598202060807) >>> location.pin("tom", 113.40603142976761, 22.511156445825442)
然后通过执行以下代码, 获取 peter 和 jack 的坐标:
>>> location.get("peter") (113.20996731519699, 23.593675019671288) >>> location.get("jack") (113.22784155607224, 23.125598202060807)
最后通过执行以下代码, 计算 peter 和 jack 之间的直线距离, 以及 peter 和 tom 之间的直线距离:
>>> location.calculate_distance("peter", "jack") 52.0944 >>> location.calculate_distance("peter", "tom") 122.0651