[英]Query all primary roads from PostGis Database filled with OSM Data within a boundary
我通过osm2pgsql将OpenStreetMap数据导入PgSQL(PostGIS),我想从包含一个区域(bbox)内所有主要道路(几何)的数据中获取SF object到R。
我迷路了,因为我也想拥有关系和节点,我不确定是否仅对 planet_osm_roads 进行查询就足够了,以及导入的数据结构与我正常使用的 osm xml 数据有何不同。 我知道这可能是一个更广泛的问题,但是
我会很感激一个开始,可以说更好地理解查询语言。
这是我的方法,但遗憾的是我得到了一个错误
conn <- RPostgreSQL::dbConnect("PostgreSQL", host = MYHOST,
dbname = "osm_data", user = "postgres", password = MYPASSWORD)
pgPostGIS(conn)
a<-pgGetGeom(conn, c("public", "planet_osm_roads"), geom = "way", gid = "osm_id",
other.cols = FALSE, clauses = "WHERE highway = 'primary' && ST_MakeEnvelope(11.2364353533134, 47.8050651144447, 11.8882527806375, 48.2423300001326)")
a<-st_as_sf(a)
这是我得到的错误:
Error in postgresqlExecStatement(conn, statement, ...) :
RS-DBI driver: (could not Retrieve the result : ERROR: syntax error at or near "ST_MakeEnvelope"
LINE 2: ...lic"."planet_osm_roads" WHERE "way" IS NOT NULL ST_MakeEnv...
^
)
Error in pgGetGeom(conn, c("public", "planet_osm_roads"), geom = "way", :
No geometries found.
In addition: Warning message:
In postgresqlQuickSQL(conn, statement, ...) :
Could not create execute: SELECT DISTINCT a.geo AS type
FROM (SELECT ST_GeometryType("way") as geo FROM "public"."planet_osm_roads" WHERE "way" IS NOT NULL ST_MakeEnvelope(11.2364353533134, 47.8050651144447, 11.8882527806375, 48.2423300001326)) a;
这是数据库:
osm_data=# \d
List of relations
Schema | Name | Type | Owner
----------+--------------------+----------+----------
public | geography_columns | view | postgres
public | geometry_columns | view | postgres
public | planet_osm_line | table | postgres
public | planet_osm_nodes | table | postgres
public | planet_osm_point | table | postgres
public | planet_osm_polygon | table | postgres
public | planet_osm_rels | table | postgres
public | planet_osm_roads | table | postgres
public | planet_osm_ways | table | postgres
public | spatial_ref_sys | table | postgres
topology | layer | table | postgres
topology | topology | table | postgres
topology | topology_id_seq | sequence | postgres
schema_name table_name geom_column geometry_type type
1 public planet_osm_line way LINESTRING GEOMETRY
2 public planet_osm_point way POINT GEOMETRY
3 public planet_osm_polygon way GEOMETRY GEOMETRY
4 public planet_osm_roads way LINESTRING GEOMETRY
Table "public.planet_osm_roads"
Column | Type | Collation | Nullable | Default
--------------------+---------------------------+-----------+----------+---------
osm_id | bigint | | |
access | text | | |
addr:housename | text | | |
addr:housenumber | text | | |
addr:interpolation | text | | |
admin_level | text | | |
aerialway | text | | |
aeroway | text | | |
amenity | text | | |
area | text | | |
barrier | text | | |
bicycle | text | | |
brand | text | | |
bridge | text | | |
boundary | text | | |
building | text | | |
construction | text | | |
您的查询看起来很好。 检查以下示例:
WITH planet_osm_roads (highway,way) AS (
VALUES
('primary','SRID=3857;POINT(1283861.57 6113504.88)'::geometry), --inside your bbox
('secondary','SRID=3857;POINT(1286919.06 6067184.04)'::geometry) --somewhere else ..
)
SELECT highway,ST_AsText(way)
FROM planet_osm_roads
WHERE
highway IN ('primary','secondary','tertiary') AND
planet_osm_roads.way && ST_Transform(
ST_MakeEnvelope(11.2364353533134,47.8050651144447,11.8882527806375,48.2423300001326, 4326),3857
);
highway | st_astext
---------+------------------------------
primary | POINT(1283861.57 6113504.88)
此图说明了 BBOX 和上例中使用的点
documentation
以获取有关 bbox 交集运算符&&
的更多信息。但是,有几件事情需要考虑。
ST_Contains
提供一个区域,请考虑简单地使用ST_DWithin
。 它基本上会做同样的事情,但你只需要提供一个参考点和距离。planet_osm_roads
中highway
类型的分布,并考虑到您的查询将始终查找primary
、 secondary
或tertiary
高速公路,创建partial index
可以显着提高性能。 正如文档所说:部分索引是建立在表的子集上的索引; 子集由条件表达式(称为部分索引的谓词)定义。 索引仅包含满足谓词的那些表行的条目。 部分索引是一项特殊功能,但在某些情况下它们很有用。
所以尝试这样的事情:
CREATE INDEX idx_planet_osm_roads_way ON planet_osm_roads USING gist(way)
WHERE highway IN ('primary','secondary','tertiary');
并且还需要对highway
进行索引。 所以试试这个..
CREATE INDEX idx_planet_osm_roads_highway ON planet_osm_roads (highway);
.. 甚至是另一个部分索引,以防您无法删除其他数据但您不需要它来做任何事情:
CREATE INDEX idx_planet_osm_roads_highway ON planet_osm_roads (highway)
WHERE highway IN ('primary','secondary','tertiary');
您始终可以识别瓶颈并检查查询计划器是否正在使用您的索引EXPLAIN
。
进一步阅读
我想到了。 这就是您从 PostGIS 数据库中获取 SF object 的方法,该数据库中填充了11.2364353533134,47.8050651144447,11.8882527806375,48.2423300001326
BBOX 内的 OSM 数据:
library(sf)
library(RPostgreSQL)
library(tictoc)
pw <- MYPASSWORD
drv <- dbDriver("PostgreSQL")
con <- dbConnect(drv, dbname = "osm_data",
host = "localhost", port = 5432,
user = "postgres", password = pw)
tic()
sf_data = st_read(con, query = "SELECT osm_id,name,highway,way
FROM planet_osm_roads
WHERE highway = 'primary' OR highway = 'secondary' OR highway = 'tertiary'AND ST_Contains(
ST_Transform(
ST_MakeEnvelope(11.2364353533134,47.8050651144447,11.8882527806375,48.2423300001326,4326)
,3857)
,planet_osm_roads.way);")
toc()
RPostgreSQL::dbDisconnect(con)
我必须验证是否确实考虑了 BBOX 值。我不确定。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.