Python 使用GeopositionField查找最近的数据库条目
我在Django中使用来存储用户的坐标。现在我想找到一个与当前用户最接近的20个用户的列表。在我的地理位置字段中可以实现该功能吗?我知道GeoDjango使搜索距离变得很容易,但由于我使用的是Heroku和postgresql,我想降低成本,而使用postgressql,安装PostGIS似乎是唯一的选择Python 使用GeopositionField查找最近的数据库条目,python,django,geolocation,geocoding,django-geoposition,Python,Django,Geolocation,Geocoding,Django Geoposition,我在Django中使用来存储用户的坐标。现在我想找到一个与当前用户最接近的20个用户的列表。在我的地理位置字段中可以实现该功能吗?我知道GeoDjango使搜索距离变得很容易,但由于我使用的是Heroku和postgresql,我想降低成本,而使用postgressql,安装PostGIS似乎是唯一的选择 有什么建议吗?快速浏览一下源代码,就会发现地理位置字段只是将坐标存储为纯文本(,),因此没有有效的方法从数据库中提取正确的数据。如果您想要高效的数据库查询,您必须使用GeoDjango或Pos
有什么建议吗?快速浏览一下源代码,就会发现
地理位置字段
只是将坐标存储为纯文本(,
),因此没有有效的方法从数据库中提取正确的数据。如果您想要高效的数据库查询,您必须使用GeoDjango或PostGIS(或者找到另一种提供空间数据搜索的替代方法) 对于两点之间的距离,可以使用Geopy
从:
下面是distance.distance的示例用法:
>>> from geopy import distance
>>> _, ne = g.geocode('Newport, RI')
>>> _, cl = g.geocode('Cleveland, OH')
>>> distance.distance(ne, cl).miles
538.37173614757057
在Django项目中实现这一点。在models.py中创建法线模型:
class User(models.Model):
name = models.Charfield()
lat = models.FloatField()
lng = models.FloatField()
要优化一点,您可以先过滤用户对象以粗略估计附近的用户。这样,您就不必遍历数据库中的所有用户。此粗略估计是可选的。为了满足所有项目要求,您可能需要编写一些额外的逻辑:
#The location of your user.
lat, lng = 41.512107999999998, -81.607044999999999
min_lat = lat - 1 # You have to calculate this offsets based on the user location.
max_lat = lat + 1 # Because the distance of one degree varies over the planet.
min_lng = lng - 1
max_lng = lng + 1
users = User.objects.filter(lat__gt=min_lat, lat__lt=max__lat, lat__gt=min_lat, lat__lt=max__lat)
# If not 20 fall back to all users.
if users.count() <= 20:
users = User.objects.all()
我认为你有两个选择:
- 您必须找到从源用户到所有用户的所有距离(这真的很重)
- 然后对所有距离进行排序,并将您要查找的20个距离排在前面
.latitude
和longitude
进行检索尽管如此,如果这是处理空间数据的唯一情况,我建议使用点域和KNN支持。因此,您将来不需要postgis支持。但要求是在不使用GeoDjango的情况下找到20个最近的用户。Yes:results=sorted(results,key=lambda k:k['distance'])按距离为您提供所有用户。[:20]给出前20个。也许你每次都需要很多用户来循环抛出。解决方案是首先粗略估计附近的用户。我将更新答案,并将粗略估计代码放在最接近的20之前。这相当聪明!但随着规模的扩大,这不是会变得更慢吗?与Postgis相比,它的效率不如空间/地理数据库。我想你应该找出哪些查询和计算花费了你(内存/速度/开发时间/金钱),并以此为基础做出决定。一个好的“粗略”估计会加快速度。也许。count()和偶极搜索?我也有类似的要求,最后也使用了geopy。我发现这个要点很有用:。它包括一个粗略的距离计算,以使查询更有效。是的,我有一个保存纬度和经度的列。我有一个从导出的边界框函数,我很容易得到一个框,它告诉我最大和最小纬度和经度的范围,但问题是如何有效地获得最近的20个用户。也许K-近邻能帮我解决这个问题。我会多读一读。但是这种方法比Postgis慢很多,不是吗?如果你使用Postgres 9.1+中实现的K-最近邻解决方案,它将与Postgis一样高效,因为它使用了空间索引(基于voronoi图)。
results = []
for user in users:
d = distance.distance((lat, lng), (user.lat, user.lng))
results.append( {'distance':d, 'user':user })
results = sorted(results, key=lambda k: k['distance'])
results = results[:20]