GeoDjango距离查询返回错误结果

9 投票
1 回答
1564 浏览
提问于 2025-04-16 22:25

我刚在我的开发机器上成功安装了GeoDjango。问题是我无法正确执行距离查询。无论我使用哪个SRID,得到的距离结果都完全不对。这里有个例子。

>>> from django.contrib.gis.measure import D
>>> from app.models import Place
>>> from django.contrib.gis.geos import Point
>>> qs = Place.objects.all()
>>> point = Point(-118, 34)
>>> qs.filter(coordinates__distance_lte=(point, D(m=1)))
[<Place: 7-Eleven>, <Place: Arthur Murray Dance Studio>, <Place: Costco>, <Place: AMC Century City 15>, <Place: 24 Hour Fitness>, <Place: Ralphs>, <Place: Houston's Restaurant>, <Place: CVS/pharmacy>, <Place: Shaky Alibi>, <Place: Sephora>, <Place: Trader Joe's>]

问题是这些地方离point的距离远远超过1米。

我尝试过调整设置,但运气不太好。这是另一个SRID的例子。

>>> qs = Place.objects.all().transform(3786)
>>> point = Point(-118, 34, srid=3786)
>>> qs.filter(coordinates__distance_lte=(point, D(m=1)))
[<Place: 7-Eleven>, <Place: Arthur Murray Dance Studio>, <Place: Costco>, <Place: AMC Century City 15>, <Place: 24 Hour Fitness>, <Place: Ralphs>, <Place: Houston's Restaurant>, <Place: CVS/pharmacy>, <Place: Shaky Alibi>, <Place: Sephora>, <Place: Trader Joe's>]

我感觉我可能选错了SRID,但我在网上找到的没有一个能正常工作,或者给出的反馈也没什么用。

非常感谢任何帮助!

1 个回答

9

我不太想自己回答自己的问题,但没有其他人来帮忙,所以我自己找到了答案。

我深入研究了PostGIS,想弄清楚问题是出在位置数据库本身还是Django上。因此,我把之前用的Django ORM查询转换成了我希望PostGIS后台接收到的理想查询。令我惊讶的是,生成的查询实际上是:

SELECT id
FROM app_place
WHERE ST_DWithin(coordinates, ST_SetSRID(ST_Point(-118, 34), 3768), 1);

这就是问题所在。我需要的查询是:

SELECT id
FROM app_place
WHERE ST_Distance_Sphere(ST_SetSRID(ST_Point(-118, 34), 3768), coordinates) < 1;

我查看了Django的源代码,想搞清楚发生了什么,发现我在coordinates字段上设置了geography=True。显然,这会改变Django在创建SQL查询时生成的PostGIS函数。虽然这个信息没有文档说明,但这里有一个相关部分

简单来说,如果你遇到这个问题,去掉模型中的geography=True就可以解决了。

撰写回答