How to return a record with the lowest distance from a point using geodjango?

不问归期 提交于 2019-12-04 12:09:59

问题


I am using geodjango and have a collection of points in my database. To get a queryset of points within a certain area I use this:

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

My question is how can I return only one point(the point with the lowest distance)from the point I have passed it?

EDIT

I should mention that I am passing in coordinates and wanting to create a Point object with them. Then pass that point in as the origin and filter against that. For example I have tried:

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

This snippet of code gives me this error:

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

Interestingly enough if I do the following:

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))

回答1:


Finally a solution gathered from clues from GeoDjango distance filter with distance value stored within model - query which lead me to this post. From this information I was able to gather that you MUST SPECIFY the measure parameter in your distance query. You will see in the below snippet, I import measure as D. Then use it in the query. If you don't specify it you will get this error:

ValueError: Tuple required for `distance_lte` lookup type.

To take just the point with the lowest distance I used 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]



回答2:


queryset = Spot.objects.distance(origin).filter(distance__lte=distance_m)
point = queryset.order_by('distance')[:1][0]

https://docs.djangoproject.com/en/dev/ref/contrib/gis/geoquerysets/#distance




回答3:


I was looking for an example on how to sort results against a location with geodjango, so my use case was very close to this one. Though the accepted solution worked, performances was very bad for a big data set (more than 140000 rows).

Short story: the distance_lte function must calculate distance to origin for each row of the table and can't make use of geo indexes. It appears that the dwithin function can make use of such indexes and don't need to actually calculate the distance to origin for each row before before the restriction is done, so it's way more efficient:

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

The dwithin function works with geographical data in degree (the "1" in the query).



来源:https://stackoverflow.com/questions/11557182/how-to-return-a-record-with-the-lowest-distance-from-a-point-using-geodjango

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!