保存前如何在rails中使用ST_GeoHash和ST_MakePoint postgis函数?

How to use ST_GeoHash and ST_MakePoint postgis functions in rails before save?

如何在 rails postgis 点中构建,然后在将响应发送给客户端之前进行 geohash 并将它们保存到数据库中?我想通过 ST_MakePointST_GeoHash 函数实现,我更愿意避免执行 SQL 并通过 [0]["st_makepoint"] 提取数据,如果可能如何将此函数插入​​到插入所有属性时自动执行它们?我已经安装了 squeel gem,也许我可以将这个函数合并到查询中吗?

我当前的rails代码:

before_save :set_geopoint
def set_geopoint
  #attributes -> {"latitude" => 51.90,"longitude" => 16.42,"geopoint" => nil}
  #self.geopoint = "ST_MakePoint(#{latitude}, #{longitude})")" #not working
  #self.geopoint = ActiveRecord::Base.connection.execute("SELECT ST_MakePoint(#{latitude}, #{longitude})")[0]["st_makepoint"]
  #self.geohash = "ST_GeoHash(#{self.geopoint})"
  #self.geohash = ActiveRecord::Base.connection.execute("SELECT ST_GeoHash(ST_SetSRID(#{self.geopoint},4326),5);").first["st_geohash"]
end

我在触发函数之前通过 SQL 做到了,但我仍在寻找 rails 方法。

CREATE FUNCTION geopoint_trigger() RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO posts( geopoint ) VALUES( ST_GeomFromText('POINT(' || NEW.latitude || ' ' ||  NEW.longitude || ')') );
  RETURN NEW;
END;
$$
LANGUAGE 'plpgsql';

要生成可以保存在支持 postgis 的数据库中的点,您需要使用工厂生成该点。你在这里做什么:

self.geopoint = "ST_MakePoint(#{latitude}, #{longitude})")" #not working

只是将 self.geopoint 设置为一个字符串并尝试保存它。由于您的数据库地理点字段(我假设)设置为接受一个点,因此它失败了。

我建议您使用 rgeo gem 将地理工厂添加到您的模型中。将其添加到您的 Gemfile.

https://github.com/rgeo/rgeo

您需要确保在迁移中使用点作为列类型,如下所示:

t.point :geopoint, geographic: true

在您的 Post 模型中,您需要像这样指定一个工厂:

RGEO_FACTORY = RGeo::Geographic.spherical_factory(srid: 4326)

并且您还需要告诉 rgeo 在您的 geopoint 列上使用哪个工厂。

set_rgeo_factory_for_column :geopoint, RGEO_FACTORY

现在在您的 before_save 中,只需执行以下操作:

self.geopoint = RGEO_FACTORY.point(latitude, longitude)

它应该可以工作...

编辑

例如,如果您想在 Rails 模型中使用 Postgis 函数来获取 GeoHash,那么您可以这样做:

post_geohash = Post.select("ST_GeoHash(geopoint) as geohash").where(id: some_post_id).geohash

您还可以创建一个在您的 Post 模型上执行此操作的实例方法:

def geohash
  Post.select("ST_GeoHash(geopoint) as geohash").where(id: id).geohash
end

不确定这是否有效,因为它未经测试,但你明白了。