2012-07-19 21 views
5

Sto usando geodjango e ho una collezione di punti nel mio database. Per ottenere un set di query di punti all'interno di una certa area io uso questo:Come restituire un record con la distanza minima da un punto utilizzando geodjango?

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

La mia domanda è come posso tornare un solo punto (il punto con la distanza più basso) dal punto ho superato esso?

EDIT

Devo dire che sto passando in coordinate e di voler creare un oggetto Point con loro. Quindi passare quel punto come origine e filtrare contro quello. Per esempio ho provato:

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 

questo frammento di codice mi dà questo errore:

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

È interessante notare che se faccio la seguente:

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

risposta

4

Infine una soluzione raccolta da indizi da GeoDjango distance filter with distance value stored within model - query che mi portano a questo post. Da queste informazioni sono stato in grado di raccogliere che tu DEVE SPECIFICARE il parametro di misura nella query di distanza. Vedrete nel frammento di seguito, importare misurare come D. Quindi utilizzalo nella query. Se non si specifica che si ottiene questo errore:

ValueError: Tuple required for `distance_lte` lookup type. 

di prendere solo il punto con la distanza più basso che ho usato 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] 
+0

puoi spiegare perché hai' [: 1] [0] 'alla fine – Sevenearths

+1

Passa a questo prima di eseguire il debug: [https://docs.djangoproject.com/en/1.6/ref/contrib/gis/db-api/# compatibility-tables] ha passato un paio di ore inutilmente al debug di point__distance_lte quando non è supportato per Mysql – PKaura

0
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

+2

Provare il tuo suggerimento Ottengo un errore. 'FieldError: Impossibile risolvere la parola chiave 'distance' nel campo. Le scelte sono: autore, created_on, id, name, point, slug, updated_on' Non c'è campo distanza sul mio modello. – darren

+0

@darren può accadere quando si dimentica all'utente 'objects = GeoManager()' Viene da 'from django.contrib.gis.db.models.manager import GeoManager' nelle impostazioni i DATABASES si ricordano di usare' 'ENGINE': ' django.contrib.gis.db.backends.postgis ', ' – andi

0

ero alla ricerca di un esempio su come ordinare risultati contro una posizione con geodjango, quindi il mio caso d'uso era molto vicino a questo. Sebbene la soluzione accettata funzionasse, le prestazioni erano molto negative per un grande set di dati (oltre 140000 righe).

Breve storia: la funzione distance_lte deve calcolare la distanza dall'origine per ogni riga della tabella e non può utilizzare gli indici geografici. Sembra che la funzione dwithin può fare uso di tali indici e non hanno bisogno di calcolare in realtà la distanza da origine per ogni riga prima prima che la restrizione è fatto, quindi è molto più efficiente:

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

La funzione dwithin lavora con dati geografici in gradi (il "1" nella query).

Problemi correlati