我有一个数据库模型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查询,我可以查询数据库中位于大的“square”(在lat / lon空间)内的位置,然后过滤那些具有更高成本的三角函数.类似以下内容:
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(expensive_but_accurate_restriction)做嵌套查询?如果没有,怎么样?
非常感谢!
解决方法
以下是如何进行嵌套查询:
LineItem.where(product_id: Product.where(price: 50))
它提出以下要求:
SELECT "line_items".* FROM "line_items" WHERE "line_items"."product_id" IN (SELECT "products"."id" FROM "products" WHERE "products"."price" = 50)
请注意,只有ids将从产品表中获取.如果您尝试以另一种方式连接两个实体,并且此魔术不合适,请使用Product.select(:some_field).where(…).