Vous pouvez utiliser un raw()
requête sql pour utiliser postgis order_by
opérateurs :
-
<->
qui obtient le voisin le plus proche en utilisant les centres des boîtes englobantes pour calculer les distances inter-objets. -
<#>
qui obtient le voisin le plus proche en utilisant les boîtes englobantes elles-mêmes pour calculer les distances inter-objets.
Dans votre cas, celui que vous voulez semble être le <->
opérateur, donc la requête brute :
knn = Person.objects.raw(
'SELECT * FROM myapp_person
ORDER BY location <-> ST_SetSRID(ST_MakePoint(%s, %s),4326)',
[location.x, location.y]
)[:k]
MODIFIER en raison de sa propre négligence : Vous pouvez omettre le [:k]
pour ajouter LIMIT 1
sur la requête SQL brute. (N'utilisez pas les deux comme je l'ai fait !)
En train de répondre à votre autre question :Est-il efficace de commander par distance (table entière) dans geodjango ,une autre solution peut-être possible :
En activant l'spatial indexing
et en affinant votre requête par des contraintes logiques (comme expliqué dans ma réponse
de la question ci-dessus), vous pouvez obtenir un KNN assez rapide requête comme suit :
current_location = me.location
people = People.objects.filter(
location__dwithin=(current_location, D(km=50))
).annotate(
distance=Distance('location', current_location)
).order_by('distance')[:k]