我遇到一个名为trip
的模型的情况。每个行程都有一个departure_airport
和arrival_airport
这两个相关字段,并且都是airport
模型的一部分。机场模型中的每个对象都有一个由latitude
和longitude
字段表示的位置。
我需要能够使用Haversine公式从两个(可能)分开的出发和到达机场位置接收输入。该公式将计算从数据库中的每个出发/到达机场到已被用作输入的机场位置之间的距离。
此查询的困难之处在于,我用出发和到达机场的位置注释了旅行查询集,但是因为有两组纬度/经度字段(每个机场一组)具有相同的名称,所以您可以在sql where子句中使用带注释的字段,我无法在查询中同时使用两组机场。
我认为解决方案是在带注释的字段上使用子查询,以便查询在where子句之前执行,但是我无法确定此查询是否可行。另一种选择是编写raw_sql。
这是我到目前为止所拥有的:
GCD_FORMULA_TO = """3961 * acos(
cos(radians(%s)) * cos(radians(arrival_lat))
* cos(radians(arrival_lon) - radians(%s)) +
sin(radians(%s)) * sin(radians(arrival_lat)))"""
GCD_FORMULA_FROM = """3961 * acos(
cos(radians(%s)) * cos(radians(departure_lat))
* cos(radians(departure_lon) - radians(%s)) +
sin(radians(%s)) * sin(radians(departure_lat)))"""
location_to = Q(location_to__lt=self.arrival_airport_rad)
location_from = Q(location_from__lt=self.departure_airport_rad)
qs = self.queryset\
.annotate(arrival_lat=F('arrival_airport__latitude_deg'))\
.annotate(arrival_lon_to=F('arrival_airport__longitude_deg'))\
.annotate(departure_lat=F('departure_airport__latitude_deg'))\
.annotate(longitude_lon=F('departure_airport__longitude_deg'))\
.annotate(location_to=RawSQL(GCD_FORMULA_TO, (self.arrival_airport.latitude_deg, self.arrival_airport.longitude_deg,
self.arrival_airport.latitude_deg)))\
.annotate(location_from=RawSQL(self.GCD_FORMULA_FROM, (self.departure_airport.latitude_deg, self.departure_airport.longitude_deg,
self.departure_airport.latitude_deg)))\
.filter(location_to and location_from)
return qs
有什么想法吗?也可以采用其他方式解决此问题。
答案 0 :(得分:1)
您很难做到这一点。
如果您的python代码具有一对位置,请使用this:
from geopy.distance import distance
loc1 = (lat1, lng1)
loc2 = (lat2, lng2)
d = distance(loc1, loc2).km
如果要查询数据库,也许您希望它运行PostGIS / Postgres,而不是mysql, 因此您可以计算distance和形状成员。 语法有时在clunky side上,但是索引的作用很大。 这是一个从伦敦希思罗机场出发的例子:
SELECT a.airport_name,
ST_Distance('SRID=4326; POINT(-0.461389 51.4775)'::geography,
ST_Point(a.longitude, a.latitude)) AS distance
FROM arrival_airports a
ORDER BY distance;
作为另一件事,您可以考虑在表上定义到达和/或离开VIEW,然后再为每个视图使用不同的模型进行JOIN。