1

所以我有一个空间查询,可以根据给定的纬度/经度获取位置。查询如下所示:

Location.
  where("ST_Distance(location, ST_GeomFromText('POINT (#{lng} #{lat})', #{SRID})) < ?", max_distance)
  .order("ST_Distance(location, ST_GeomFromText('POINT (#{lng} #{lat})', #{SRID}))")

由于这里的 lat/lng 是用户的 lat/lng,并且 DB 正在对每条记录执行距离查询。如何保存此结果以供以后使用?在我看来,我显示了距离,我最终不得不以更慢的方式重新计算它。

存储此顺序方程结果的最佳方法是什么?

4

3 回答 3

1

我得到了一个解决方案,可以满足我的要求select AS

Location.
  .select("*, ST_Distance(location, ST_GeomFromText(#{point}, #{SRID})) AS distance_from_user")
  .where("ST_Distance(location, ST_GeomFromText('POINT (#{lng} #{lat})', #{SRID})) < ?", max_distance)
  .order("distance_from_user")

这使我能够调用location.distance_from_user视图并获取在数据库中计算的值。

于 2018-07-20T15:43:13.263 回答
0

如果您想将此数据存储在数据库中,您将需要一个新表,因为存储在 User 或 Location 表中都不起作用,因为用户与其可能的位置之间存在多对多关系。

您可以创建一个Distances具有 、 和 的新表,user_idlocation_id使用distancerails 中的关联进行设置:

class User
  has_many :distances
end

然后查询与用户的距离:

current_user.distances.where("distance < 5").order("distance")

但是,在您的情况下,不需要存储在数据库中,因为您只需要可用于请求的其余部分的数据。您可以通过选择另一个(计算的)列以及您的模型来做到这一点,这将“持久”到您的视图中:

Location
  .select("*")
  .select("ST_Distance(location, ST_GeomFromText('POINT (#{lng} #{lat})', #{SRID}) AS distance_from_user")
  .where("distance_from_user < ?", max_distance)
  .order("distance_from_user")

然后在您看来,distance_from_user像使用任何其他属性一样使用:

于 2018-07-20T14:24:02.220 回答
0

编辑:我误解了你的问题,所以在下面重写:

将您的查找作为方法存储在模型上(我假设所有值都存储在用户表中,但我没有使用 SRID,因此如果未保存,请随时修改):

class User < ApplicationRecord
  def location_lookup(lng=self.lng, lat=self.lat, SRID=self.SRID)
    result = Location
    .where("ST_Distance(location, ST_GeomFromText('POINT (#{lng} #{lat})', #{SRID})) < ?", max_distance)
    .order("ST_Distance(location, ST_GeomFromText('POINT (#{lng} #{lat})', #{SRID}))")
  end
end

然后假设您正在使用 Devise,或者以其他方式使用查找定义用户,您可以在任何控制器操作中通过调用current_user.location_lookup或传递参数(如果需要)来调用它。在缓存和将其存储为实例变量之间,我认为它不会经常为单个用户访问数据库。

于 2018-07-20T07:51:38.120 回答