我的数据库模型是Position(lat,lon)
,它保存了纬度
和经度
。
我有一个名为show_close_by
的控制器动作,它接收一个以度为单位的位置 (my_lat, my_lon)
,一个公差(以千米为单位),并应返回数据库中在公差范围内的位置列表。
为此,我使用haversine_distance公式计算两个坐标 (lat1,lon1,lat2,lon2)
之间在地球表面上的距离(以公里为单位)。
为了使查询更快,我在查询中编写了整个 haversine_distance
公式:
... WHERE 2*6371*asin(sqrt( power( sin( (:lat2-latitude)*pi()/(180*2) ) ,2) + cos(latitude*pi()/180)*cos(:lat2*pi()/180)*power(sin( (:lon2-longitude)*pi()/(180*2) ),2) )) < tolerance
查询语句的具体内容并不重要。我的疑问是:是否需要对数据库中的每个位置都计算这个巨大的函数?我能否使用一个简单一些的函数来过滤掉那些明显距离太远的位置呢?
嗯,我可以:通过一个嵌套的SQL查询,我可以查询在一个大的“正方形”(在纬度/经度空间中)内的位置,然后过滤掉那些需要更多成本的三角函数。像下面这样:
SELECT * FROM ( SELECT * FROM Positions WHERE lat-latitude < some_reasonable_upper_bound AND lon-longitude < same_upper_bound ) WHERE costly_haversine_distance < tolerance
最后,我的问题是:我如何在Rails中实现这一点(而不必自己编写整个查询)?Positions.where(reasonable_upper_bound).where(costly_but_accurate_restriction)
是否会生成嵌套查询?如果不是,那应该怎么做?
非常感谢!
Position.near([40.71, 100.23], 20)
这样的事情了。这个gem非常受欢迎,所以我想他们能很好地完成你想做的事情。(只是让你知道,链接where
子句并不能实现你想要的效果。我认为它只是覆盖了之前的子句)。 - RobinAND
将条件追加到当前查询中,这并不完全符合提问者的要求。 - nzifnab