GeoDjango:如何执行空间接近记录的查询

GeoDjango: How to perform a query of spatially close records

我有两个 Django 模型(A 和 B),它们没有任何外键关联,但都有一个几何字段。

class A(Model):
    position = PointField(geography=True)

class B(Model):
    position = PointField(geography=True)

我想在空间上关联它们,即给定 A 的查询集,能够获得 B 的查询集,其中包含与 A 的距离小于给定距离的那些记录。

我还没有找到使用纯 Django 的 ORM 来做这样的事情的方法。

当然,我可以在A中写一个属性,比如这个:

@property
def nearby(self):
    return B.objects.filter(position__dwithin=(self.position, 0.1))

但这只允许我在每个实例上获取附近的记录,而不是在单个查询中,效率很低。

我也试过这样做:

nearby = B.objects.filter(position__dwithin=(OuterRef('position'), 0.1))
query = A.objects.annotate(nearby=Subquery(nearby.values('pk')))

list(query)  # error here

但是,最后一行出现此错误:

ValueError: This queryset contains a reference to an outer query and may only be used in a subquery

有没有人知道执行此类查询的更好方法(更有效)或者我的代码失败的原因?

非常感谢。

我终于设法解决了它,但最后我不得不执行原始 SQL 查询。

这将 return 所有带有注释的 A 记录,包括附近所有 B 记录的列表:

from collections import namedtuple

from django.db import connection


with connection.cursor() as cursor:
    cursor.execute('''SELECT id, array_agg(b.id) as nearby FROM myapp_a a
                      LEFT JOIN myapp_b b ON ST_DWithin(a.position, p.position, 0.1)
                      GROUP BY a.id''')

    nt_result = namedtuple('Result', [col[0] for col in cursor.description])
    results = [nt_result(*row) for row in cursor.fetchall()]

参考文献: