如何使用geodjango返回距离某个点最近的记录?

6

我正在使用Geodjango,并且数据库中有一些点的集合。为了获取在特定区域内的点的查询集,我使用以下代码:

queryset = Spot.objects.filter(point__distance_lte=(origin, distance_m))

我的问题是如何只返回我已经通过的点中距离最近的那个点?
编辑
我应该提到,我正在传递坐标,并希望创建一个带有这些坐标的点对象。然后将该点作为原点传递并筛选。 例如,我尝试过:
from spots.models import *
from django.contrib.gis.geos import *

origin = Point(28.011030, -26.029430)
distance_m = 1000

queryset = Spot.objects.filter(point__distance_lte=(origin, distance_m))
for q in queryset:
    print q.distance

这段代码给我报错:

Traceback (most recent call last):
  File "<console>", line 2, in <module>
AttributeError: 'Spot' object has no attribute 'distance'

有趣的是,如果我按照以下方式操作:

origin = Spot.objects.get(name='Montecasino').point
distance_m = 1000

for city in Spot.objects.distance(origin):
    print(city.name, city.distance)

(u'Design Quarter Parking', Distance(m=677.347841801))
(u'Montecasino', Distance(m=0.0))
(u'Fourways', Distance(m=1080.67723755))
3个回答

4

终于有了一个解决方案,这个方案从GeoDjango distance filter with distance value stored within model - query的线索中得出,它引导我到了这篇文章。通过这些信息,我发现在距离查询中必须指定测量参数。 在下面的代码片段中,你会看到我导入了measure作为D,然后在查询中使用它。 如果你不指定它,你会得到这个错误:

ValueError: Tuple required for `distance_lte` lookup type.

为了选择距离最近的点,我使用了 order_by('distance')[:1][0]
from spots.models import *
from django.contrib.gis.geos import *
from django.contrib.gis.measure import D

distance_m = 20000
origin = Point(28.011030, -26.029430)

closest_spot = Spot.objects.filter(point__distance_lte=(origin, D(m=distance_m))).distance(origin).order_by('distance')[:1][0]

你能解释一下为什么在结尾处有[:1][0]吗? - Robert Johnstone
1
请在调试之前仔细阅读此内容:[https://docs.djangoproject.com/en/1.6/ref/contrib/gis/db-api/#compatibility-tables]。当使用Mysql时,如果不支持point__distance_lte,则可能会浪费几个小时进行无意义的调试。 - PKaura

0

我正在寻找一个关于如何使用geodjango根据位置对结果进行排序的示例,所以我的用例非常接近这个问题。尽管被接受的解决方案可行,但对于大型数据集(超过140000行)而言性能非常糟糕。

简单来说:distance_lte函数必须计算表中每一行的距离原点的距离,并且无法利用地理索引。似乎dwithin函数可以利用这些索引,并且在限制执行之前不需要实际计算每一行到原点的距离,因此效率更高:

origin = Point(28.011030, -26.029430)
closest_spot = Spot.objects.filter(point__dwithin=(origin, 1)) \
    .distance(origin).order_by('distance')[:1][0]

dwithin 函数使用以度为单位的地理数据(查询中的“1”)。


0

2
尝试了您的建议后,我遇到了一个错误。FieldError: 无法将关键字“distance”解析为字段。可选项为:author、created_on、id、name、point、slug、updated_on 我的模型中没有距离字段。 - darren
@darren 当你忘记使用 objects = GeoManager() 时,这种情况可能会发生。它来自于在设置中的 from django.contrib.gis.db.models.manager import GeoManager。在 DATABASES 中记得使用 'ENGINE': 'django.contrib.gis.db.backends.postgis', - andilabs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接