我正在尝试在Django中处理一个基本商店定位器的邻近搜索。而不是在我的应用程序中使用PostGIS,以便我可以使用GeoDjango的距离过滤器,我想在模型查询中使用Cosines距离公式的球面定律。为了提高效率,我希望所有的计算都在数据库中完成。
一个来自互联网的MySQL查询示例实现了球面余弦定律,如下所示:
SELECT id, (
3959 * acos( cos( radians(37) ) * cos( radians( lat ) ) *
cos( radians( lng ) - radians(-122) ) + sin( radians(37) ) *
sin( radians( lat ) ) )
)
AS distance FROM stores HAVING distance < 25 ORDER BY distance LIMIT 0 , 20;
字符串
查询需要为每个商店的纬度/纬度值引用Zipcode ForeignKey。我如何在Django模型查询中实现所有这些功能?
8条答案
按热度按时间yhuiod9q1#
有可能执行raw SQL queries in Django。
我的建议是,编写查询来拉取一个ID列表(看起来你现在正在做),然后使用ID来拉取关联的模型(在一个常规的、非原始的SQL Django查询中)。尽量保持SQL与方言无关,这样如果你不得不切换数据库,你就不必再担心一件事了。
为了澄清,这里有一个如何做到这一点的例子:
字符串
作为免责声明,我不能保证这段代码,因为我已经有几个月没有写任何Django了,但它应该是沿着正确的路线。
zte4gxcn2#
为了跟进Tom的回答,它在SQLite中默认不工作,因为SQLite默认缺少数学函数。没问题,添加它非常简单:
字符串
xoefb8l83#
为了跟进Tom,如果你想有一个在postgresql中也能工作的查询,你不能使用AS,因为你会得到一个错误,说'distance'不存在。
你应该把整个球面定律表达式放在WHERE子句中,像这样(它在mysql中也有效):
字符串
请注意,您必须选择纬度和经度,否则您不能在WHERE子句中使用它。
qybjjes14#
为了跟进jboxer的回答,下面是作为自定义管理器的一部分的整个过程,其中一些硬编码的东西变成了变量:
字符串
2exbekwf5#
JBoxer的回应
字符串
这返回了我的汽车从x数量的英里,这工作得很好。然而,原始查询返回多远,他们从某个位置,我认为fieldname是'距离'。
我怎样才能返回这个字段'距离'与我的汽车对象?
guykilcj6#
使用上面提出的一些答案,我得到了不一致的结果,所以我决定再次使用[这个链接] http://www.movable-type.co.uk/scripts/latlong.html作为参考来检查方程,方程是
d = acos(sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(lon2-lon1) ) * 6371
,其中d
是要计算的距离,lat1,lon1
是基点的坐标,lat2,lon2
是其他点的坐标,在我们的例子中,这些点是数据库中的点。从上面的答案来看,
LocationManager
类如下所示字符串
使用网站[链接] http://www.movable-type.co.uk/scripts/latlong.html作为检查,我的结果一致。
cbeh67ev7#
使用Django的数据库函数也可以做到这一点,这意味着你可以使用
.annotate()
调用添加一个distance_miles
列,然后按它排序。下面是一个例子:字符串
z0qdvdin8#
@classmethod def nearby_locations(cls,latitude,longitude,radius,max_results=1000,use_miles=False):if use_miles:distance_unit = 3959 else:distance_unit = 6371000
字符串