在 Ruby 内调用 PostGIS 函数
Calling PostGIS functions within Ruby
我需要在 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 使用 gem squeel
展示了一个很好的例子:
my_polygon = get_my_polygon # Obtain the polygon as an RGeo geometry
MySpatialTable.where{st_intersects(lonlat, my_polygon)}.first
由于这不再是当前 README 的一部分,我想知道是否不推荐这样做,或者是否有更好的选择。
这里有两个问题需要解决
第一个是在 .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_date
和 total_price
属性。
这给我们带来了第二个问题,即 Rails 没有给我们一个简单的方法来参数化 select
(即使用 ?
占位符),所以(据我所知)你需要自己做 sanitize_sql_array
:
sql_for_select_intersection = sanitize_sql_array([
"ST_ASEWKT(ST_INTERSECTION(geometry, ?)) AS intersection",
geometry,
])
这将 return 一个经过清理的 SQL 片段,如 ST_ASEWKT(ST_INTERSECTION(geometry, '...'))
,然后您可以使用它来指定 select
中的字段:
Trip.where(status: "active").select(:id, sql_for_select_intersection))
生成的查询将 return 具有 id
和 intersection
属性的 Trip 对象。
我需要在 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 使用 gem squeel
展示了一个很好的例子:
my_polygon = get_my_polygon # Obtain the polygon as an RGeo geometry
MySpatialTable.where{st_intersects(lonlat, my_polygon)}.first
由于这不再是当前 README 的一部分,我想知道是否不推荐这样做,或者是否有更好的选择。
这里有两个问题需要解决
第一个是在 .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_date
和 total_price
属性。
这给我们带来了第二个问题,即 Rails 没有给我们一个简单的方法来参数化 select
(即使用 ?
占位符),所以(据我所知)你需要自己做 sanitize_sql_array
:
sql_for_select_intersection = sanitize_sql_array([
"ST_ASEWKT(ST_INTERSECTION(geometry, ?)) AS intersection",
geometry,
])
这将 return 一个经过清理的 SQL 片段,如 ST_ASEWKT(ST_INTERSECTION(geometry, '...'))
,然后您可以使用它来指定 select
中的字段:
Trip.where(status: "active").select(:id, sql_for_select_intersection))
生成的查询将 return 具有 id
和 intersection
属性的 Trip 对象。