五分钟实现地理空间API:PostgREST+PostGIS

news/2024/7/9 19:59:16 标签: postgresql, docker
  • 如何用PostgREST、PostgreSQL和PostGIS构建强大的空间restapi?
    以往我们在使用PostGIS做空间分析或者需要前端进行WFS或者空间分析的时候,可能会使用GeoServer发布图层,或者用Geotools自定义,但是使用
    如何用PostgREST就不需要了,我们一起看看如何实现吧。

如何用PostgREST

在本教程中,你将学习如何使用强大的PostgREST库在其引擎盖下构建一个SpatialRESTAPI—只需几分钟!
我们将使用以下功能实现一系列不同的API:

  • 计算字符串的长度
  • 计算多边形的面积
  • 求两个多边形的交集

如果您以前从未听说过PostgREST,那么让我们看看作者是怎么说的:
PostgREST是一个独立的web服务器,它将PostgreSQL数据库直接转换为restfulapi。数据库中的结构约束和权限决定了API端点和操作。
再简单不过了。

准备

要实现本教程的所有步骤,需要安装PostgreSQL、PostGIS和PostgREST。您可以使用我们的安装教程,它将帮助您建立并运行一个docker容器,PostgREST将在随后的步骤中使用它。

安装和设置PostgreSQL、PostGIS和PostgREST本文不详细讨论,详见如下地址或者本公众号的专题文章:

https://github.com/gis-ops/tutorials/blob/postgrest-elevation-api/postgres/postgres_postgis_postgrest_installation.md

步骤1-让我们返回一个简单的GeoJSON对象

如前所述,我们将实现动态计算空间信息的存储过程。作为用户,您将能够将GeoJSON对象作为有效负载发布到API。为了演示,我们将从一个简单的过程开始,它将返回有效载荷而不更改它。

让我们回到psql提示符:

sudo docker exec -it postgrest_tut psql -U postgres

我们将在api模式中添加一个简单的函数。它接受一个JSON参数,然后按原样返回它。

CREATE OR REPLACE FUNCTION api.singlegeojsonparam(single_param json) RETURNS json

    LANGUAGE sql
    AS $_$
    SELECT single_param;

$_$;

按回车键。。。就这样,我们来试试吧!

curl -X POST \
  http://localhost:3000/rpc/singlegeojsonparam \
  -H 'Content-Type: application/json' \
  -H 'Prefer: params=single-object' \
  -d '{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[100.0,0.0],[101.0,0.0],[101.0,1.0],[100.0,1.0],[100.0,0.0]]]},"properties":{"prop0":"value1","prop1":{"this":"that"}}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[100.0,0.0],[101.0,0.0],[101.0,1.0],[100.0,1.0],[100.0,0.0]]]},"properties":{"prop0":"value2","prop1":{"this":"that"}}}]}'

如果你对发送JSON数据的POST请求不太熟悉,这可能对您来说有点陌生。body只是一个JSON对象,通常它的键会被解释为body参数。但是,通过指定请求头Prefer:params=single object,我们可以让后端知道将整个POST主体解释为单个参数的值。对于只需要一个JSON对象的端点来说非常方便。

步骤2-计算字符串的长度

现在我们可以从一些有趣的事情开始。让我们继续编写一个函数,该函数能够计算wgs84也就是EPSG4326。注意,我们提供的GeoJSON是以度为单位的,因此我们必须转换为pseudo-mercator(或类似的东西)。另外,我们将把它转换成数字,然后除以1.000(以公里为单位得到结果),我们将它四舍五入到2位小数。

CREATE OR REPLACE FUNCTION api.calc_length(linestring json) RETURNS numeric AS $$

    SELECT ROUND(
      CAST(
        ST_Length(
          ST_Transform(
            ST_GeomFromGeoJSON(LineString), 54030
          )
        )/1000 AS numeric
      ),2
    )

$$ LANGUAGE SQL;

很简单。让我们试试看。

curl -X POST \
  http://localhost:3000/rpc/calc_length \
  -H 'Content-Type: application/json' \
  -H 'Prefer: params=single-object' \
  -d '{"type":"LineString","coordinates":[[-101.744384,39.32155],[-101.552124,39.330048],[-101.403808,39.330048],[-101.332397,39.364032],[-101.041259,39.368279],[-100.975341,39.304549],[-100.914916,39.245016],[-100.843505,39.164141],[-100.805053,39.104488],[-100.491943,39.100226],[-100.437011,39.095962],[-100.338134,39.095962],[-100.195312,39.027718],[-100.008544,39.010647],[-99.865722,39.00211],[-99.684448,38.972221],[-99.51416,38.929502],[-99.382324,38.920955],[-99.321899,38.895308],[-99.113159,38.869651],[-99.0802,38.85682],[-98.822021,38.85682],[-98.448486,38.848264],[-98.206787,38.848264],[-98.020019,38.878204],[-97.635498,38.873928]],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}'

喂!返回美国堪萨斯州的边界数据是:

367.15

单位是公里!

步骤3-计算多边形的面积

到目前为止,您很可能已经掌握了实现定制函数是多么容易的要点。类似于线串的例子,我们也可以计算多边形的面积。让我们让这变得更加棘手,让用户发送一个GeoJSON FeatureCollection。为了简单一点,端点只能处理FeatureCollection的第一个特征,因此只能处理一个多边形。

CREATE OR REPLACE FUNCTION api.calc_area(featurecollection json) RETURNS numeric AS $$

    SELECT ROUND(
      CAST(
        ST_Area(
          ST_Transform(
            ST_GeomFromGeoJSON(
              featurecollection->'features'->0->'geometry'
            ), 54030
          )
        )/1000000 AS numeric
      ),2
    )

$$ LANGUAGE SQL;

让我们看看结果:

curl -X POST \
  http://localhost:3000/rpc/calc_area \
  -H 'Content-Type: application/json' \
  -H 'Prefer: params=single-object' \
  -d '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-73.6962890625,41.02135510866602],[-73.8446044921875,41.253032440653186],[-74.168701171875,41.20758898181025],[-74.44335937499999,40.88444793903562],[-74.520263671875,40.60144147645398],[-74.2840576171875,40.53050177574321],[-73.8885498046875,40.63479884404164],[-72.83935546875,40.805493843894155],[-72.6800537109375,40.950862628132775],[-73.6962890625,41.02135510866602]]],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}}]}'

我们的多边形覆盖了纽约的一部分

6017.49

单位是平方公里。

步骤4-计算2个多边形的交集

最后,让我们再实现一个函数来计算两个多边形的交集。现在的功能应该是不言而喻的。我们只需要确保返回的是GeoJSON而不是数值。

CREATE OR REPLACE FUNCTION api.calc_intersection(featurecollection json) RETURNS json AS $$

      SELECT ST_AsGeoJSON(
        ST_Intersection(
          ST_GeomFromGeoJSON(
            featurecollection->'features'->0->'geometry'
          ),
          ST_GeomFromGeoJSON(
            featurecollection->'features'->1->'geometry'
          )
        )
      )::json;

$$ LANGUAGE SQL;

我们将用一个包含2个多边形的特性集合来调用这个API。

curl -X POST \
  http://localhost:3000/rpc/calc_intersection \
  -H 'Content-Type: application/json' \
  -H 'Prefer: params=single-object' \
  -d '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-73.6962890625,41.02135510866602],[-73.8446044921875,41.253032440653186],[-74.168701171875,41.20758898181025],[-74.44335937499999,40.88444793903562],[-74.520263671875,40.60144147645398],[-74.2840576171875,40.53050177574321],[-73.8885498046875,40.63479884404164],[-72.83935546875,40.805493843894155],[-72.6800537109375,40.950862628132775],[-73.6962890625,41.02135510866602]]],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-73.6798095703125,41.56203190200195],[-74.3280029296875,41.75492216766298],[-74.34997558593749,41.74262728637672],[-74.7894287109375,41.21998578493921],[-74.29504394531249,40.87614141141369],[-73.4326171875,40.91766362458114],[-73.6798095703125,41.56203190200195]]],"crs":{"type":"name","properties":{"name":"EPSG:4326"}}}}]}'

它将以GeoJSON交集响应。

{
  "type": "Polygon",
  "coordinates": [
      [
          [
              -74.3926939034368,
              40.944056911669
          ],
          [
              -74.168701171875,
              41.2075889818102
          ],
          ...
      ]
  ]
}

总结

恭喜您完成本教程。现在,您将了解如何使用PostGIS设置和使用PostgREST web API进行空间分析和查询。

与其他框架相比,它可能是我们遇到过的最直接的web框架。这显然只触及了可能的表面,但是如果您正在寻找一种快速的方法来设置API来动态处理空间计算,我们绝对可以推荐使用PostgREST。


http://www.niftyadmin.cn/n/1372101.html

相关文章

PostGIS系统表之SPATIAL_REF_SYS

在PostGIS中最重要的两张OGC 元数据表:SPATIAL_REF_SYS和GEOMETRY_COLUMNS。 SPATIAL_REF_SYS表保存空间数据库中使用的坐标系统的数字ID和文本描述。 如我们最常用的WGS84坐标系代号为EPSG:4326。 SPATIAL_REF_SYS表和空间参考系统 spacear_ref_sys表是一个包含PostGIS且符…

在PostGIS中表达复杂几何对象是如何定义的

PostGIS符合开放地理空间联盟(OGC)的OpenGIS规范。因此,许多PostGIS方法要求进行操作的几何既简单又有效。例如,计算在多边形外部定义了孔的多边形的面积,或者根据非简单边界线构造多边形是没有意义的。 根据OGC规范,简单几何是没有异常几何点(例如自相交或自相切)的几…

PostGIS中的拓扑关系及函数(一)

PostGIS提供了若干拓扑关系函数,本文介绍如下函数: 1. ST_3DIntersects #相交 2. ST_Contains #包含 3. ST_ContainsProperly #完全包含 4. ST_Covers #覆盖 5. ST_CoveredBy #被覆盖 6. ST_Crosses #空间…

PostGIS中的拓扑关系及函数(二)

PostGIS提供了若干拓扑关系函数,本文介绍如下函数: 1. ST_LineCrossingDirection #线之间的交叉方向 2. ST_Disjoint #不相交 3. ST_Equals #相等ST_LineCrossingDirection-线之间的交叉方向 定义 integer ST_LineCrossin…

Greenplum数据库中使用PostGIS扩展

本文包含以下内容: 关于 PostGISGreenplum 数据库中的PostGIS 扩展提供PostGIS能力升级Greenplum的PostGIS扩展迁移PostGIS 1.4到2.0使用PostGIS 功能和限制 1. 关于 PostGIS 关于PostGIS的介绍,本文不再赘述,请参考本公众号相关专题文章。…

什么是地理空间AI或Geo.AI?

创新的技术改造未来该行业的驱动方式。通过使用智能算法,数据分类和智能预测分析,人工智能可以在众多领域发挥作用。 将GIS的精确性与锋利的分析和基于解决方案的AI相结合的AI的更具体子集称为地理空间AI,或简称为 Geo.AI。 地理空间AI也可以…

PostGIS数据库中的几种复杂查询举例

本文包含以下内容: 利用索引空间查询SQL示例 有效地使用PostGIS需要知道哪些空间功能可用,并确保适当的索引可用以提供良好的性能。这些示例中使用的SRID 312仅用于演示。您应该使用spatial_ref_sys表中列出的REAL SRID,并使用与数据投影相匹…

PostGIS中的空间索引(一)

本文介绍如下索引: GISTBRIN 索引使使用空间数据库处理大型数据集成为可能。 如果不建立索引,则对功能的任何搜索都需要对数据库中的每个记录进行“顺序扫描”。 索引通过将数据组织到可以快速遍历以查找特定记录的搜索树中来加快搜索速度。 PostgreSQL…