【问题标题】:How to do location based query with simple Django filter?如何使用简单的 Django 过滤器进行基于位置的查询?
【发布时间】:2020-11-06 12:27:26
【问题描述】:

我已将用户的坐标保存在 User 模型中。帖子模型具有latitudelongituderadius 字段。只有该(帖子)附近的用户才能看到该帖子。我不知道如何在这里使用filter(),所以我使用了以下方法:

post=Posts.objects.all()
for a in post:
    distance= geopy.distance.geodesic((lat1,lng1), (a.latitude, a.longitude)).km
    print(distance)
    if distance < a.radius:
        p.append(a)    
    else:
        continue

这里,lat1lng1 是当前User 的坐标。建议是否有更好的方法,因为这似乎非常低效。

【问题讨论】:

  • 如果您使用 PostGIS 或 SpatiaLite 数据库,您可以使用 GeoDjango 查询。
  • @WillemVanOnsem 我可以,但是对于我想做的一个简单查询来说很麻烦。我很确定必须有一种简单的方法来完成这项工作。
  • 在内部,此类数据库通常使用spatial k-d tree 来索引数据。这使得查找通常需要 O(log n) 而不是线性方法。
  • @WillemVanOnsem PostGIS 就是这样。谢谢你。如果有人对此有独特的方法,我会保持开放状态。

标签: django django-models django-views django-queryset


【解决方案1】:

根据您的要求,您可以使用正方形而不是圆形。预先计算正方形的 x-max、x-min、y-max 和 y-min 边界,然后在数据库中进行简单的User.filter(lat__gt=lat_min, user.lng__gt=lng_min, user.lat__lt=lat_max ... 查找。

在过去的项目中,我使用过这个:

def get_latlng_bounderies(lat, lng, distance):
    """
    Return min/max lat/lng values for a distance around a latlng.
    :lat:, :lng: the center of the area.
    :distance: in km, the "radius" around the center point.
    :returns: Two corner points of a square that countains the circle,
              lat_min, lng_min, lat_max, lng_max.
    """
    gc = great_circle(kilometers=distance)
    p0 = gc.destination((lat, lng), 0)
    p90 = gc.destination((lat, lng), 90)
    p180 = gc.destination((lat, lng), 180)
    p270 = gc.destination((lat, lng), 270)

    ret = p180[0], p270[1], p0[0], p90[1]
    return ret

它不是一个圆形,所以它不完全围绕正方形的“角”,但它更快,因为它在数据库中进行了简单的浮点比较。

【讨论】:

  • 这是解决这个问题的非常聪明的方法。我会分析我的要求,也许我会使用它。谢谢你这么棒的回答。
猜你喜欢
  • 2017-12-14
  • 1970-01-01
  • 1970-01-01
  • 2011-12-25
  • 1970-01-01
  • 1970-01-01
  • 2020-10-28
  • 2020-10-22
  • 2019-07-31
相关资源
最近更新 更多