在Ruby中调用PostGIS函数

时间:2019-06-11 15:51:21

标签: ruby postgis squeel rgeo

我需要在Ruby的SQL SELECT子句中执行PostGIS函数st_intersection。目前,我将其作为原始SQL查询:

sql_query = "SELECT id, ST_ASEWKT(ST_INTERSECTION(geometry, ?)) FROM trips WHERE status='active';"
intersections = Trip.execute_sql(sql_query, self[:geometry].to_s)

这种方式的缺点是我以文本形式接收结果,并且需要从字符串中解析出对象。使用ActiveRecord接口进行查询会更好。但是,我找不到在ActiveRecord中运行PostGIS功能(例如st_intersection)的任何解决方案。

activerecord-postgis-adapter的早期版本README显示了一个使用宝石squeel的好例子:

my_polygon = get_my_polygon    # Obtain the polygon as an RGeo geometry
MySpatialTable.where{st_intersects(lonlat, my_polygon)}.first

由于这不再是当前自述文件的一部分,我想知道是否建议不要这样做,或者是否有更好的选择。

1 个答案:

答案 0 :(得分:2)

这里要解决两个问题。

第一个是在.select子句中使用SQL函数。通常,这很容易-您只需使用AS为结果命名。这是来自ActiveRecord Rails Guide的示例:

Order.select("date(created_at) as ordered_date, sum(price) as total_price").group("date(created_at)")

生成的Order对象将具有ordered_datetotal_price属性。

这给我们带来了第二个问题,那就是Rails没有给我们提供一种简单的方法来参数化select(即使用?占位符),因此(据我所知)告诉),您需要自己使用sanitize_sql_array

sql_for_select_intersection = sanitize_sql_array([
  "ST_ASEWKT(ST_INTERSECTION(geometry, ?)) AS intersection",
  geometry,
])

这将返回经过清理的SQL片段,例如ST_ASEWKT(ST_INTERSECTION(geometry, '...')),您可以使用该片段在select中指定字段:

Trip.where(status: "active").select(:id, sql_for_select_intersection))

结果查询将返回具有idintersection属性的Trip对象。