Postgis/PostgreSQL

作者

杰夫麦克纳

联系

jmckenna在gatewaygeomatics.com

最后更新

2022-04-25

Postgis/PostgreSQL

PostGIS 在空间上启用开放源码 PostgreSQL 数据库。

这个 PostGIS wiki page 可能包括其他信息。

小技巧

确保已将扩展加载到数据库中: 创建扩展PostGIS;

小技巧

如果您已升级PostGIS,请确保在数据库上执行以下操作: SELECT postgis_extensions_upgrade();

数据访问/连接方法

Postgis由MapServer直接支持,必须编译到MapServer才能工作。

PostgreSQL客户端库( libpq.solibpq.dll )必须存在于系统的路径环境中,才能提供功能。

这个 CONNECTIONTYPE 参数必须设置为POSTGIS。

这个 CONNECTION 参数用于指定连接到数据库的参数。连接参数可以采用任何顺序。大多数是可选的。 数据库名 是必需的。 user 是必需的。 host 默认为本地主机, port 默认为5432(PostgreSQL的标准端口)。

数据参数用于指定用于绘制地图的数据。数据的形式是“[表名SQL U子查询]中的[几何体_列]使用唯一的[唯一的_键]使用srid=[空间_引用_id]”。绘制功能时,“使用唯一”和“使用srid=”子句是可选的,但使用它们可以提高性能。如果要对PostGIS层进行MapServer查询调用,则数据参数必须包含“using unique”。省略它将导致查询失败。

小技巧

如果您正在尝试执行查询并接收消息 "ERROR: column oid does not exist at character..." 很可能您错过了 using unique 数据参数中的一部分。如果您没有指定唯一的ID列,那么MapServer将尝试查找一个ID列(代价是再执行几个查询)。因此,最好是 始终 在数据语句中指定唯一ID列。如果您的表没有唯一ID列,则可以添加一个列,如下所示:

ALTER TABLE mytable ADD COLUMN unique_id SERIAL PRIMARY KEY;

警告

从PostgreSQL 12.0版开始,从PostgreSQL中删除了OID。建议在图层的DATA语句中为映射文件指定不同的唯一ID列。

备注

通过使用支持变量绑定 BINDVALS 和名称值对。

下面是一个简单的通用示例:

CONNECTIONTYPE POSTGIS
CONNECTION "host=yourhostname dbname=yourdatabasename user=yourdbusername
            password=yourdbpassword port=yourpgport"
DATA "geometrycolumn from yourtablename"

此示例显示如何在数据行中指定唯一键和srid:

CONNECTIONTYPE POSTGIS
CONNECTION "dbname=yourdatabasename user=yourdbusername"
DATA "the_geom from the_database using unique gid using srid=4326"

此示例显示如何使用SQL子查询在数据库内执行联接并将结果映射到MapServer。注意语句中的“as subquery”字符串——从“from”到“using”之间的所有内容都将发送到数据库进行评估:

CONNECTIONTYPE POSTGIS
CONNECTION "dbname=yourdatabasename user=yourdbusername"
DATA "the_geom from (select g.gid, g.the_geom, a.attr1, a.attr2 from
      geotable g join attrtable a on g.gid = a.aid) as subquery
      using unique gid using srid=4326"

此示例显示如何使用几何函数和数据库排序来限制返回到MapServer的要素和顶点的数量:

CONNECTIONTYPE POSTGIS
CONNECTION "dbname=yourdatabasename user=yourdbusername"
DATA "the_geom from (select g.gid, ST_Simplify(g.the_geom, 10.0) as
      the_geom from geotable g order by ST_Area(g.the_geom) desc
      limit 10) as subquery using unique gid using srid=4326"

这个例子展示了的用法!盒子!替换字符串以覆盖SQL中映射边界框的默认包含。默认情况下,空间框子句将附加到数据子句中的SQL,但您可以使用!盒子!在语句中任意位置插入它。一般来说,您不需要使用!盒子!,因为PostgreSQL规划器将从生成的SQL生成最佳计划,但在某些情况下(复杂的子查询),通过放置可以生成更好的计划!盒子!靠近查询中间:

CONNECTIONTYPE POSTGIS
CONNECTION "dbname=yourdatabasename user=yourdbusername"
DATA "the_geom from (select g.gid, ST_Union(g.the_geom, 10.0) as
      the_geom from geotable g where ST_Intersects(g.geom,!BOX!)) as
      subquery using unique gid using srid=4326"

Ogrinfo示例

可以使用ogrinfo直接从数据库中读取关于postgis表的元数据。

首先,应使用“--formats”命令确保GDAL/OGR构建包含PostgreSQL驱动程序:

>ogrinfo --formats

  Supported formats:
  ...
    PGeo -vector- (ro): ESRI Personal GeoDatabase
    MSSQLSpatial -vector- (rw+): Microsoft SQL Server Spatial Database
    PostgreSQL -vector- (rw+): PostgreSQL/PostGIS
    MySQL -vector- (rw+): MySQL
  ...

如果你没有司机,你可能想试试 FWToolsMS4W 包,其中包括驱动程序。

一旦您有了驱动程序,就可以尝试在数据库上使用ogrinfo命令来获取空间表列表:

>ogrinfo PG:"host=127.0.0.1 user=postgres password=postgres dbname=canada port=5432"
      using driver `PostgreSQL' successful.
      1: province (Polygon)

现在使用ogrinfo获取有关空间表结构的信息:

>ogrinfo PG:"host=127.0.0.1 user=postgres password=postgres dbname=canada port=5432" province -summary

 INFO: Open of `PG:host=127.0.0.1 user=postgres password=postgres dbname=canada'
    using driver `PostgreSQL' successful.

  Layer name: province
  Geometry: Polygon
  Feature Count: 1068
  Extent: (-2340603.750000, -719746.062500) - (3009430.500000, 3836605.250000)
  Layer SRS WKT:
  PROJCS["NAD83 / Canada Atlas Lambert",
      GEOGCS["NAD83",
          DATUM["North_American_Datum_1983",
              SPHEROID["GRS 1980",6378137,298.257222101,
                  AUTHORITY["EPSG","7019"]],
              TOWGS84[0,0,0,0,0,0,0],
              AUTHORITY["EPSG","6269"]],
          PRIMEM["Greenwich",0,
              AUTHORITY["EPSG","8901"]],
          UNIT["degree",0.0174532925199433,
              AUTHORITY["EPSG","9122"]],
          AUTHORITY["EPSG","4269"]],
      PROJECTION["Lambert_Conformal_Conic_2SP"],
      PARAMETER["standard_parallel_1",49],
      PARAMETER["standard_parallel_2",77],
      PARAMETER["latitude_of_origin",49],
      PARAMETER["central_meridian",-95],
      PARAMETER["false_easting",0],
      PARAMETER["false_northing",0],
      UNIT["metre",1,
          AUTHORITY["EPSG","9001"]],
      AXIS["Easting",EAST],
      AXIS["Northing",NORTH],
      AUTHORITY["EPSG","3978"]]
  FID Column = ogc_fid
  Geometry Column = wkb_geometry
  ...

Mapfile 示例

LAYER
  NAME "province"
  STATUS ON
  TYPE POLYGON
  CONNECTIONTYPE POSTGIS
  CONNECTION "host=127.0.0.1 user=postgres password=postgres port=5432 dbname=canada"
  DATA "wkb_geometry FROM province USING UNIQUE ogc_fid USING srid=3978"
  EXTENT -2340603.750000 -719746.062500 3009430.500000 3836605.250000 # for maximum performance
  PROCESSING "CLOSE_CONNECTION=DEFER" # for maximum performance
  CLASS
    NAME "Provincial Land"
    STYLE
      COLOR 240 240 240
      OUTLINECOLOR 199 199 199
    END
  END
  PROJECTION #source
    "init=epsg:3978"
  END
END

有关postgis和地图服务器的更多信息,请参阅postgis文档:https://postgis.net/documentation/

PostGIS栅格(PGRaster)

从PostGIS 2.0版本开始,PostGIS包括对栅格数据的支持,可以通过MapServer(通过GDAL)访问栅格数据。

小技巧

确保已将扩展加载到数据库中: CREATE EXTENSION postgis_raster;

加载栅格数据

您必须使用 栅格2pgsql 要将栅格数据加载到PostGIS中(请参见 postgis.net 以供使用),例如:

raster2pgsql -s 2961 -I -C -M -F -t auto -l 2,4,8 colorhillshade_dtm_1m_utm20_w_10_91.tif lunenburg_colorhillshade > raster.sql
psql -U postgres -p 5432 -d mydb -f raster.sql

以上将创造一个新的 lunenburg_colorhillshade 来自GeoTIFF文件的表。

在MapServer中显示的要点:
  • 请务必将 -t 切换以平铺栅格

  • 请务必将 -I 切换以在栅格上创建概要索引

  • 请务必将 -C 切换以应用栅格约束

  • 请务必将 -F 切换以添加具有栅格文件名称的列

与GDALINFO连接

使用 gdalinfo 用于列出数据库中可用栅格表的实用程序,例如:

gdalinfo PG:"host=127.0.0.1 port=5432 user=postgres password=postgres dbname=mydb"

它返回类似如下的内容:

Driver: PostGISRaster/PostGIS Raster driver

Subdatasets:
  ...
    SUBDATASET_3_NAME=PG:host=127.0.0.1 port=5432 user=postgres password=postgres dbname=mydb  schema='public' table='lunenburg_colorhillshade' column='rast'
    SUBDATASET_3_DESC=PostGIS Raster table at public.lunenburg_colorhillshade (rast)
  ...

接下来,指定 表格立柱 ,使用 -nomd 交换机,例如:

gdalinfo PG:"host=127.0.0.1 port=5432 user=postgres password=postgres dbname=mydb table=lunenburg_colorhillshade column=rast" -nomd

它返回栅格的摘要,包括其投影 (EPSG:2961 _):

Driver: PostGISRaster/PostGIS Raster driver
Coordinate System is:
PROJCS["NAD83(CSRS) / UTM zone 20N",
    GEOGCS["NAD83(CSRS)",
        DATUM["NAD83_Canadian_Spatial_Reference_System",
            SPHEROID["GRS 1980",6378137,298.257222101,
                AUTHORITY["EPSG","7019"]],
            TOWGS84[0,0,0,0,0,0,0],
            AUTHORITY["EPSG","6140"]],
        PRIMEM["Greenwich",0,
            AUTHORITY["EPSG","8901"]],
        UNIT["degree",0.0174532925199433,
            AUTHORITY["EPSG","9122"]],
        AUTHORITY["EPSG","4617"]],
    PROJECTION["Transverse_Mercator"],
    PARAMETER["latitude_of_origin",0],
    PARAMETER["central_meridian",-63],
    PARAMETER["scale_factor",0.9996],
    PARAMETER["false_easting",500000],
    PARAMETER["false_northing",0],
    UNIT["metre",1,
        AUTHORITY["EPSG","9001"]],
    AXIS["Easting",EAST],
    AXIS["Northing",NORTH],
    AUTHORITY["EPSG","2961"]]

Mapfile 层

The mapfile layer is similar to other raster layers, but the PostGIS connection parameters are specified in the DATA parameter, such as:

LAYER
  NAME "lunenburg_raster"
  TYPE RASTER
  STATUS ON
  DATA "PG:host=127.0.0.1 port=5432 sslmode=disable user=postgres password=postgres dbname=mydb schema=public table=lunenburg_colorhillshade column=rast mode=2"
  PROJECTION
    "init=epsg:2961"
  END
  CLASS
    NAME "Lunenburg"
  END
  PROCESSING "CLOSE_CONNECTION=DEFER"
END # layer

备注

该参数 mode=2 必须在数据连接字符串中指定,才能使MapServer正确加载,因为栅格是平铺的。请参阅 PostGIS Raster Driver 有关更多信息,请访问页面。

使用shp2img进行测试

shp2img -m postgis.map -o ttt.png -map_debug 3

  msDrawMap(): rendering using outputformat named png (AGG/PNG).
  msDrawMap(): WMS/WFS set-up and query, 0.000s
  msDrawRasterLayerLow(lunenburg_raster): entering.
  msDrawMap(): Layer 1 (lunenburg_raster), 0.355s
  msDrawMap(): Drawing Label Cache, 0.000s
  msDrawMap() total time: 0.356s
  msSaveImage(ttt.png) total time: 0.004s
../../_images/pgraster.png

支持2.5d几何图形

除了水平坐标(X、Y或经度、纬度)之外,PostGIS还可以支持具有垂直分量的几何图形,通常称为2.5D几何图形。

从mapserver 7.0开始,如果mapserver是在-dwith_point_z_m=on上构建的,则会考虑这样的2.5d几何图形。

备注

WFS中2.5D几何图形的输出要求在层级别指定显式元数据项。见 WFS server 文档。

备注

通过设置以下处理选项,仍然可以强制仅从PostGIS检索二维几何图形。

PROCESSING "FORCE2D=YES"

支持sql/mm曲线

PostGIS能够存储圆形内插曲线,作为SQL多媒体应用程序空间规范的一部分(阅读 SQL/MM specification

有关PostGIS支持的更多信息,请参阅 SQL-MM Part 3 部分,例如 here

从mapserver 6.0开始,postgis的特点是可以通过mapserver直接绘制出循环字符串、复合曲线、曲线多边形、多曲线和多曲面。

示例1:MapServer中的循环字符串

以下是加载到PostGIS中的功能的已知文本:

INSERT INTO test ( g, id ) VALUES ( ST_GeomFromText('CIRCULARSTRING(0 0,
                                    4 0, 4 4, 0 4, 0 0)', -1), 2);

MAPServer层的示例如下:

LAYER
  NAME "curves_poly"
  STATUS DEFAULT
  TYPE POLYGON
  CONNECTIONTYPE postgis
  CONNECTION "user=postgres password=postgres dbname=curves host=localhost port=5432"
  DATA "g from test using SRID=-1 using unique id"
  CLASS
    STYLE
      COLOR 128 128 128
      ANTIALIAS true
    END
  END
END

和测试 Sp2IMG 应生成以下地图图像:

../../_images/circularstring.png

示例2:MapServer中的复合曲线

以下是加载到PostGIS中的功能的已知文本:

INSERT INTO test ( g, id ) VALUES ( ST_GeomFromText('COMPOUNDCURVE(
                  CIRCULARSTRING(0 0, 1 1, 1 0),(1 0, 0 1))', -1), 3);

MAPServer层的示例如下:

LAYER
  NAME "curves_poly"
  STATUS DEFAULT
  TYPE POLYGON
  CONNECTIONTYPE postgis
  CONNECTION "user=postgres password=postgres dbname=curves host=localhost port=5432"
  DATA "g from test using SRID=-1 using unique id"
  CLASS
    STYLE
      COLOR 128 128 128
      ANTIALIAS true
    END
  END
END

和测试 Sp2IMG 应生成以下地图图像:

../../_images/compoundcurve.png

示例3:MapServer中的曲线多边形

以下是加载到PostGIS中的功能的已知文本:

INSERT INTO test ( g, id ) VALUES ( ST_GeomFromText('CURVEPOLYGON(
                  CIRCULARSTRING(0 0, 4 0, 4 4, 0 4, 0 0),(1 1, 3 3,
                  3 1, 1 1))', -1), 4);

MAPServer层的示例如下:

LAYER
  NAME "curves_poly"
  STATUS DEFAULT
  TYPE POLYGON
  CONNECTIONTYPE postgis
  CONNECTION "user=postgres password=postgres dbname=curves host=localhost port=5432"
  DATA "g from test using SRID=-1 using unique id"
  CLASS
    STYLE
      COLOR 128 128 128
      ANTIALIAS true
    END
  END
END

和测试 Sp2IMG 应生成以下地图图像:

../../_images/curvepolygon.png

示例4:MapServer中的多曲线

以下是加载到PostGIS中的功能的已知文本:

INSERT INTO test ( g, id ) VALUES ( ST_GeomFromText('MULTICURVE((0 0,
                  5 5),CIRCULARSTRING(4 0, 4 4, 8 4))', -1), 6);

MAPServer层的示例如下:

LAYER
  NAME "curves_poly"
  STATUS DEFAULT
  TYPE POLYGON
  CONNECTIONTYPE postgis
  CONNECTION "user=postgres password=postgres dbname=curves host=localhost port=5432"
  DATA "g from test using SRID=-1 using unique id"
  CLASS
    STYLE
      COLOR 128 128 128
      ANTIALIAS true
    END
  END
END

和测试 Sp2IMG 应生成以下地图图像:

../../_images/multicurve.png

示例5:MapServer中的多曲面

以下是加载到PostGIS中的功能的已知文本:

INSERT INTO test ( g, id ) VALUES ( ST_GeomFromText('MULTISURFACE(
                  CURVEPOLYGON(CIRCULARSTRING(0 0, 4 0, 4 4, 0 4,
                  0 0),(1 1, 3 3, 3 1, 1 1)),((10 10, 14 12, 11 10,
                  10 10),(11 11, 11.5 11, 11 11.5, 11 11)))', -1), 7);

MAPServer层的示例如下:

LAYER
  NAME "curves_poly"
  STATUS DEFAULT
  TYPE POLYGON
  CONNECTIONTYPE postgis
  CONNECTION "user=postgres password=postgres dbname=curves host=localhost port=5432"
  DATA "g from test using SRID=-1 using unique id"
  CLASS
    STYLE
      COLOR 128 128 128
      ANTIALIAS true
    END
  END
END

和测试 Sp2IMG 应生成以下地图图像:

../../_images/multisurface.png

使用MapServer<6.0

如果无法升级到MapServer 6.0,则可以使用MapServer层中的postgis函数*st_curveToline()*绘制曲线(请注意,这要慢得多):

LAYER
  NAME "curves_poly"
  STATUS DEFAULT
  TYPE POLYGON
  CONNECTIONTYPE postgis
  CONNECTION "user=postgres password=postgres dbname=curves host=localhost port=5432"
  DATA "wkb_geometry from (select c.id, ST_CurveToLine(c.g) as
                           wkb_geometry from c) as subquery using
                           unique id using SRID=-1"
  CLASS
    STYLE
      COLOR 128 128 128
      ANTIALIAS true
    END
  END
END