2

我在 Django 中使用GeopositionField来存储我的用户的坐标。现在我想找到最接近当前用户的 20 个用户的列表。我的 GeopositionField 可以实现该功能吗?我知道 GeoDjango 可以轻松搜索距离,但由于我使用的是 Heroku 和 postgresql,我想降低成本,并且使用 postgressql,安装 PostGIS 似乎是唯一的选择。

有什么建议么?

4

3 回答 3

8

对于两点之间的距离,您可以使用 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()

计算你的用户和 users 中每个用户的距离,按距离排序,得到前 20 个。

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]
于 2013-07-30T10:16:10.160 回答
1

我认为您在这里有两个选择:

  1. 如果没有空间索引(Postgis 和 Geodjango 使用 PointField)并使用 GeopositionField,就没有有效的方法。我发现处理这个问题的唯一方法是:

    • 您必须找到从源用户到所有用户的所有距离(这真的很重)。
    • 然后对所有距离进行排序,并排在您要查找的 20 位之前。

    GeopositionField 将坐标存储为文本,但可以使用.latitudelongitude在字段上检索。

  2. Postgresql 9.1+ ( http://wiki.postgresql.org/images/4/46/Knn.pdf )中似乎支持 K-Nearest-Neighbors 问题。但是,我认为您必须在表中添加另一列来存储点(http://www.postgresql.org/docs/9.2/static/datatype-geometric.html)或为 GeopositionField 实现距离函数。

如果您只是将 Heroku 的基本设置用于开发并计划更改为更高的计划,我建议您使用第一种方法,因为其他 Heroku 计划支持 Postgis,您可以轻松实现此方法,然后将其更改为简单的 Postgis函数调用。

虽然,如果这是您处理空间数据的唯一情况,我建议使用 Point 字段和 KNN 支持。因此,您将来不需要 postgis 支持。

于 2013-07-30T22:57:28.823 回答
0

对源代码的快速浏览表明,它GeopositionField只是将坐标存储为纯文本 ( <latitude>,<longitude>),因此没有一种有效的方法可以从数据库中提取正确的数据。如果您想要高效的数据库查询,则必须使用 GeoDjango 或 PostGIS(或寻找另一种提供空间数据搜索的替代方案)。

于 2013-07-30T09:47:00.977 回答