如何获得geodjango的k个最近邻居?
Posted
技术标签:
【中文标题】如何获得geodjango的k个最近邻居?【英文标题】:How do I get the k nearest neighbors for geodjango? 【发布时间】:2018-01-06 09:27:21 【问题描述】:假设我有以下模型:
class Person:
id = models.BigAutoField(primary_key=True)
name = models.CharField(max_length=150)
location = models.PointField()
如何使用 geodjango 按位置获取 k 个最近邻 (KNN)? 我必须为此编写自定义 SQL 吗? 我正在将 PostgreSQL 与 PostGIS 一起使用。
【问题讨论】:
【参考方案1】:您可以使用raw()
sql 查询来利用 postgis order_by
运算符:
<->
使用边界框的中心来计算对象间距离。
<#>
使用边界框本身来计算对象间距离。
在您的情况下,您想要的似乎是 <->
运算符,因此是原始查询:
knn = Person.objects.raw(
'SELECT * FROM myapp_person
ORDER BY location <-> ST_SetSRID(ST_MakePoint(%s, %s),4326)',
[location.x, location.y]
)[:k]
由于自己的愚蠢而编辑:您可以省略 [:k]
以在原始 SQL 查询中添加 LIMIT 1
。 (不要像我一样使用两者!)
在回答您的另一个问题的过程中:How efficient is it to order by distance (entire table) in geodjango,可能还有另一种解决方案:
通过启用spatial indexing
并通过逻辑约束缩小查询范围(如上述链接问题的in my answer 所述),您可以实现非常快速的KNN 查询,如下所示:
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]
【讨论】:
对于这种场景(获取knn),使用geography列是否还有帮助?还是毫无意义 - 因为我假设涉及<->
的计算会有所不同
您可以使用地理列或几何列。加快查询速度最重要的是使用spatial_idex
。有关该主题的进一步阅读,请看这里:boundlessgeo.com/2011/09/…Good lucky @Alan :)
您好,回头看看您的回答,我对knn = Person.objects.raw('SELECT * FROM myapp_person...
中LIMIT 1
的用途感到困惑,我们为什么需要它?
@Alan 这将返回第一个最近的邻居。你可以随意改变!我也会在我的回答中对此进行编辑。
我以为[:k]
处理好了?我很困惑,因为 LIMIT K
和 [:k]
似乎在这里服务于相同的目的以上是关于如何获得geodjango的k个最近邻居?的主要内容,如果未能解决你的问题,请参考以下文章