【问题标题】:How do I get the k nearest neighbors for geodjango?如何获得geodjango的k个最近邻居?
【发布时间】: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 一起使用。

【问题讨论】:

    标签: python django postgresql postgis geodjango


    【解决方案1】:

    您可以使用raw() sql 查询来利用 postgis order_by 运算符:

    1. <-> 使用边界框的中心来计算对象间距离。

    2. <#> 使用边界框本身来计算对象间距离。

    在您的情况下,您想要的似乎是 <-> 运算符,因此是原始查询:

    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列是否还有帮助?还是毫无意义 - 因为我假设涉及 &lt;-&gt; 的计算会有所不同
    • 您可以使用地理列或几何列。加快查询速度最重要的是使用spatial_idex。有关该主题的进一步阅读,请看这里:boundlessgeo.com/2011/09/…Good lucky @Alan :)
    • 您好,回头看看您的回答,我对knn = Person.objects.raw('SELECT * FROM myapp_person...LIMIT 1 的用途感到困惑,我们为什么需要它?
    • @Alan 这将返回第一个最近的邻居。你可以随意改变!我也会在我的回答中对此进行编辑。
    • 我以为[:k] 处理好了?我很困惑,因为 LIMIT K[:k] 似乎在这里服务于相同的目的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    • 2016-09-10
    • 1970-01-01
    • 2011-05-09
    • 2013-08-11
    • 1970-01-01
    相关资源
    最近更新 更多