当前位置: 代码迷 >> 综合 >> 五分钟实现地理空间API:PostgREST+PostGIS
  详细解决方案

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

热度:25   发布时间:2024-02-19 23:47:51.0
  • 如何用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 jsonLANGUAGE sqlAS $_$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。