在rails-postgres-rgeo项目中按纬度/经度查找记录

时间:2018-08-20 10:03:04

标签: ruby-on-rails geometry postgis rgeo

具有表Neighborhoods,如下所示:

id: 1,
title: "Sun City",
state: "CA",
geometry: "MULTIPOLYGON (((-117.1935499999999 33.74306900000005, -117.1935729999999 33.74198700000005, -117.19369999999992 33.73596500000008, -117.18936799999994 33.73584000000005, -117.18935499999992 33.72862400000008, -117.18935399999992 33.72801800000008, -117.18925499999995 33.72163400000005, -117.18921699999993 33.719152000000065, -117.18921699999993 33.71860200000009, -117.18910699999992 33.717250000000035, -117.18907999999993 33.715738000000044, -117.18896999999993 33.71498200000008, -117.18896999999993 33.71418100000005, -117.18866899999995 33.712829000000056, -117.18855899999994 33.71266900000006, -117.18844899999993 33.711959000000036, ...

geometry-是大量的lon / lat对。 我希望能够通过latlon查找邻居。

现在我正在使用此方法:

def is_within_or_intersects?(lat, lon)
  factory = RGeo::Cartesian.factory
  point = factory.point(lon, lat)
  boundary = factory.parse_wkt(self.geometry)
  point.intersects?(boundary) || point.within?(boundary)
end

但是该方法很慢,要使用该方法,我需要全部加载并遍历每个Neighoborhood

最好使用一些SQL查询来立即加载具有指定lat/lon的邻居,而不是遍历所有对象。

我尝试过此操作(例如,对Lat Lon进行了硬编码):

ActiveRecord::Base.connection.execute("SELECT * FROM neighborhoods WHERE ST_Contains(ST_Transform(ST_SetSRID(geometry, 2263), 4326), ST_GeometryFromText('POINT(-117.18757899999991 33.709771000000046)', 4326))")

但是我明白了:

ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR:  function st_setsrid(character varying, integer) does not exist
LINE 1: ...FROM neighborhoods WHERE ST_Contains(ST_Transform(ST_SetSRID...
                                                             ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

1 个答案:

答案 0 :(得分:1)

由于您的几何字段不是几何类型字段,所以返回错误。您的数据只是WKT / EWKT格式的文本字段。 首先将文本字段强制转换为几何类型,并且应该可以正常工作。

SELECT * 
  FROM neighborhoods 
 WHERE ST_Contains(ST_Transform(ST_SetSRID(st_geomfromtext(geometry), 2263), 4326), 
                   ST_GeometryFromText('POINT(-117.18757899999991 33.709771000000046)', 4326))")

如果我建议您将几何数据的数据类型(以WKT文本格式存储的文本)更改为GEOGRAPHY类型(当您使用SRID 4326时,这将是使用PostGIS的最佳和最简便的方法功能) 您也可以使用PostGIS函数st_astext()st_asewkt()轻松地将数据从GEOGRAPHY / GEOMETRY类型返回到WKT / EWKT。

使用GEOGRAPHY / GEOMETRY格式,您可以使用GIST索引,这将大大加快SQL语句的速度。

有关PostGis数据磁带here

的更多信息