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

时间:2019-04-19 23:32:46

标签: python django postgis django-orm geodjango

我有两个Django模型(A和B),它们与任何外键都不相关,但都具有一个geometry字段。

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

有人知道执行这种查询的更好方法(更有效)还是我的代码失败的原因?

非常感谢。

1 个答案:

答案 0 :(得分:1)

我终于设法解决了这个问题,但最后我必须执行原始SQL查询。

这将返回带有注释的所有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()]

参考文献: