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.hibernate</groupId>
            <artifactId>hibernate-spatial</artifactId>
            <version>5.6.0.Final</version>
        </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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值