Django PostGIS 计算两点距离实现异常,请问正确方案是什么?
Django PostGIS 两点距离计算问题排查与解决
现有代码存在的问题
- 坐标系与类型不匹配:你定义的
pin字段为geography=True、SRID=4326(WGS84经纬度坐标系),但计算时传入的目标点使用SRID=26918投影坐标系,且强制转换为geometry类型,和存储字段的类型、坐标系完全不一致,直接计算必然得到错误结果。 - 距离排序运算符误用:
<->运算符要求两侧的空间数据类型、SRID完全一致,你当前写法中一侧是geography类型、另一侧是geometry类型,排序逻辑完全失效。 - 返回逻辑错误:遍历RawQuery结果时直接返回第一条数据的
description,无法得到前3条匹配结果,也没有返回计算得到的距离值。 - 冗余操作:
ST_Transform(pin, 4326)属于无效操作,pin本身SRID就是4326,不需要再转换。
推荐实现方式(Django ORM原生支持,无需手写SQL)
首先导入依赖:
from django.contrib.gis.db.models.functions import Distance from django.contrib.gis.geos import Point
查询代码如下:
# 构造目标点,参数顺序为(经度, 纬度),指定SRID=4326和存储字段匹配 target_point = Point(-95.3385, 30.7245, srid=4326) # 注解距离字段、按距离排序、取前3条 nearby_points = lctnp.objects.annotate( distance=Distance('pin', target_point) ).order_by('distance')[:3] # 构造返回结果,distance默认单位为米 res = [ { "id": item.id, "description": item.description, "distance_m": float(item.distance.m) } for item in nearby_points ] return JsonResponse(res, safe=False)
修正后的原生SQL实现
如果你需要使用原生SQL,修正后的代码如下:
query = ''' SELECT id, description, ST_Distance(pin, ST_SetSRID(ST_MakePoint(-95.3385, 30.7245), 4326)::geography) AS dist FROM house_lctnp ORDER BY pin <-> ST_SetSRID(ST_MakePoint(-95.3385, 30.7245), 4326)::geography LIMIT 3; ''' res = [] for p in lctnp.objects.raw(query): res.append({ "id": p.id, "description": p.description, "distance_m": p.dist }) return JsonResponse(res, safe=False)
内容的提问来源于stack exchange,提问作者user3188348
相关产品推荐
相关产品推荐

