How do I get the k nearest neighbors for geodjango?

自古美人都是妖i 提交于 2021-01-24 09:18:51

问题


Assume that I have the following model:

class Person:
     id       = models.BigAutoField(primary_key=True)
     name     = models.CharField(max_length=150)
     location = models.PointField()

How would I go by obtaining the k nearest neighbors (KNN) by location using geodjango?
Would I have to write custom SQL for that?
I am using PostgreSQL with PostGIS.


回答1:


You can use a raw() sql query to utilize postgis order_by operators:

  1. <-> which gets the nearest neighbor using the centers of the bounding boxes to calculate the inter-object distances.

  2. <#> which gets the nearest neighbor using the bounding boxes themselves to calculate the inter-object distances.

In your case the one you want seems to be the <-> operator, thus the raw query:

knn = Person.objects.raw(
    'SELECT * FROM myapp_person 
    ORDER BY location <-> ST_SetSRID(ST_MakePoint(%s, %s),4326)',
    [location.x, location.y]
)[:k]

EDIT due to own derpiness: You can omit the [:k] to add LIMIT 1 on the raw SQL query. (Don't use both as I did!)


In the process of answering your other question: How efficient is it to order by distance (entire table) in geodjango ,another solution maybe possible:

By enabling spatial indexing and narrowing down your query through logical constrains (as explained in my answer of the above -linked question) you can achieve a pretty fast KNN query as follows:

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]


来源:https://stackoverflow.com/questions/45405183/how-do-i-get-the-k-nearest-neighbors-for-geodjango

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