首页 > 解决方案 > GeoDjango:如何执行空间接近记录的查询

问题描述

我有两个 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

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

我非常感谢。

标签: pythondjangopostgisdjango-ormgeodjango

解决方案


我终于设法解决了它,但最后我不得不执行一个原始的 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()]

参考:


推荐阅读