pg数据库中postgis的使用

做项目中遇到一个问题,计算经纬度坐标之间的距离,每次都使用方法计算可能非常耗时,恰好pg数据库中有postGIS这个插件,可以建立空间数据库,直接使用数据库的方法计算,非常方便

安装postGIS插件

首先去网站下载对应的版本的插件插件网址,我的pg是13版本的,所以下载13版本,下载之后就可以安装了,但是需要注意,插件和数据库安装的同一目录下,我的数据库安装目录是D:\software\PostgreSQL\13,所以插件也要安装在这个目录下面。不然会报错

postGIS的使用

1、在postgrsql中添加扩展,在控制台执行语句

CREATE EXTENSION postgis;

2、向已有表中添加空间字段location

ALTER TABLE pois ADD COLUMN location geometry;
#也可以使用下面的添加字段
ALTER TABLE pois ADD COLUMN location geometry(point,4326);
SELECT AddGeometryColumn('public', 'pois', 'location', 4326, 'POINT', 2);

这里的Geometry和4326都是数据类型和坐标系类型。
postGIS中有两种空间类型,分别是geometry和geography,geometry既支持平面对象也支持空间对象,而geography只支持空间对象,平常使用的经纬度坐标(86.309976 42.325686)既可以存储成geography类型,也可以存储成geometry类型。而4326表示geometry是空间对象。
需要注意的是,一般情况下,我们使用geometry类型,因为geometry类型支持的方法较多,便于查询和计算,而且geography类型的方法执行耗时比geometry多。那么什么时候使用geography类型呢,地图范围较大,需要担心投影细节的情况,就需要使用geography类型。

3、根据表pois中已有字段longitude,latitude给空间字段赋值

update pois SET location = st_geometryfromtext('POINT('|| longitude||' '|| latitude||')',4326);

4、计算
计算距离
float ST_Distance(geometry g1, geometry g2);
float ST_Distance(geography gg1, geography gg2);
float ST_Distance(geography gg1, geography gg2, boolean use_spheroid);
float ST_DistanceSphere(geometry geomlonlatA, geometry geomlonlatB);

SELECT id,ST_Distance(location,ST_geomfromText('point(86.309976 42.325686)',4326),true) FROM POIS;

由于我们是geometry类型,这里使用ST_Distance计算距离,但是需要设置use_spheroid=true,返回的是球面距离,更接近于实际距离,如果不加true,则计算的不是距离非常小,应该是度数。也可以使用ST_DistanceSphere直接计算
返回40米内的点

select * from pois where ST_DWithin(geom, ST_GeomFromText('POINT(86.309978 42.325974)', 4326),40,true);

这里ST_DWithin方法后面需要加上true,否则返回的结果不正确
参考文章postgresql 空间数据操作,POSTGIS常用函数,Chapter 8. PostGIS Reference

项目应用

springboot项目
导入依赖

        <dependency>
            <groupId>org.hibernategroupId>
            <artifactId>hibernate-spatialartifactId>
            <version>5.6.0.Finalversion>
        dependency>

字段映射

@Column(name="location",columnDefinition = "geometry(Point,4326)")
Point location;

这里存储的是点所以是point,另外我测试了一下,geography也可以这样映射成geometry(Point,4326)
查询语句,这里使用的是JPA技术

    @Query(nativeQuery=true, value  = "select * from pois where ST_DWithin(location ,(:point),:distance,true);")
    List<POI> findWithinGeometry(@Param("point") Point point, @Param("distance")Integer distance);

你可能感兴趣的:(postgresql,数据库,postgresql,database)