空间数据是指用来表示空间实体的位置、形状、大小及其分布特征诸多方面信息的数据,它可以用来描述来自现实世界的目标,它具有定位、定性、时间和空间关系等特性,操作空间数据主要是指对点、线、面等基本结构的一个操作。

        在PostgreSQL数据库中也可以存储这些空间数据,存储时可以是geometry格式,也可以以shape文件的格式存储。geometry是以十六进制串组成的,表示的是几何形状;shape文件存储的是wkt(Well-Know Text)类型的数据,对应点线面分别由三种类型:POINT、LINE、POLYGON来表示,这是单一的类型,对应的联合类型又有MULTIPOINT、MULTILINE、MULTIPOLYGON等。并且PostgreSQL提供了一些操作空间数据的函数,能够比较简单方便的对空间数据进行查询、插入、转换等。本文中主要介绍了怎么基于PostgreSQL操作geometry类型的空间数据。

        想要在Postgresql中储存或者操作空间数据,首先需要安装并扩展空间数据库(Postgis)引擎,普通安装下的Postgresql是没有Postgis功能的,无法对geometry类型的数据进行操作。扩展包postgis的下载地址是Getting Started | PostGIS,可以直接下载exe执行文件,此处需注意要保证和本地已经安装的Postgresql版本保持一致。

        当安装Postgis后,Postgresql只是有了地理空间分析的支持,在具体的数据库中仍然不能使用,比如在未扩展Postgis的数据库中,新建一张表,表中的字段类型是geometry,此时会报“geometry”类型不存在问题,如下图所示。这是因为我们并没有创建空间数据库,因此无法使用。

        此时需要为指定数据库手动创建一个空间数据库才可以,创建方式是在当前数据库中执行以下sql语句:CREATE EXTENSION postgis。

执行完后,在数据库的扩展下可以看到多了一个postgis行,如下图左侧pcka_db数据库所示,而右边的ctm01efenalarm_db是没有扩展空间数据库的。

     

三、操作空间数据

        简介中提到PostgreSQL存储空间数据的格式有两种,分别是geometry和wkt,无论哪一种,其字段的数据类型都是geometry。在DBeaver数据库可视化工具中,都是用wkt形式展示geometry数据类型的,因此我们看到的都是如下形式的数据:其中POLYGON是一个面的空间数据,POINT是一个点的空间数据。

 

        为了直观看到geometry格式下的展示效果,我们可以使用pg数据库自带的一个开源图形工具pgAdmin4来查看geometry格式的数据展示效果,如下图所示。

 

        我们也可以编写java代码将geom字段取出来时,debug可以看出geometry格式的数据,如下图所示。

        从以上两个方式查看的geometry格式的数据是以一系列十六进制串组成的,只不过 DBeaver工具在数据展示的时候自动帮我们进行了转化而已。因此在java读取空间数据时,就涉及到了geometry格式和wkt格式的转化,对于geometry类型的字段:

  1. insert时:需要将wkt转换成geometry保存到数据库
  2. select时:需要再次将geometry转回wkt显示

PostgreSQL提供了下面两种转化操作函数,分别是:

  • ST_GeomFromText(wkt,坐标系参数):将wkt格式数据转化成geometry格式,其中第一个参数是wkt类型的数据,第二个是坐标系参数,常用的有4490即CGCS2000大地坐标系、4326地理坐标系等。
  • ST_AsText(geometry):将geometry格式转化成wkt格式

除了以上两个转换函数以外,还有其他一些常用的函数:

  • st_centroid(geometry):获取某个geometry的中心点
  • st_intersects(geometry,geometry):实现两个geometry的相交
  • st_union(geom):实现多个geometry的联合

四、实际使用效果 

        在实际查询数据库时,需要将geometry转成wkt,否则查询出来的是一连串的十六进制数据,无法使用,而本质上wkt就是一种用文本形式描述,因此java中可以直接使用String来接收wkt类型的数据。如下是查询sql语句。

转换完以后我们在java代码中获取的geom字段如下所示,可以看出转换以后的数据与DBeaver工具中看到的相同。

        对于前端来说,可以直接处理wkt类型的空间数据,因此将结果直接返给前端到页面进行展示。如果前端不好处理或者后续需要在代码里继续处理空间数据时,只需操作字符串即可。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐