MySQL空间数据存储及函数


Posted in MySQL onSeptember 25, 2021

前言:

不久前开发了一个地图相关的后端项目,需要提供一些点线面相关的存储、查询、分析相关的操作,于是对MySQL空间函数进行充分调研并应用在项目中;MySQL为空间数据存储及处理提供了专用的类型geometry(支持所有的空间结构),还有有细分类型Point, LineString, Polygon,MultiPoint,MultiLineString,MultiPolygon等等,我们了解了空间函数,在涉及到经纬度存储,路线存储方面的业务就能够使用此类型进行存储,使用相关空间函数进行分析业务实现,以下所有数据库操作基于MySQL5.7.20

一、数据类型

1.什么是MySQL空间数据

  • MySQL提供了数据类型geometry用来存储坐标信息,geometry类型支持以下三种数据存储
MySQL空间数据存储及函数

还有多点MULTIPOINT(多点)、MULTILINESTRING(多线)、MULTIPOLYGON(多面)、GEOMETRYCOLLECTION(集合,可放入点线面)等类型

2.什么是geojson

GeoJSON是一种对各种地理数据结构进行编码的格式。GeoJSON对象可以表示几何、特征或者特征集合。GeoJSON支持下面几何类型:点、线、面、多点、多线、多面和几何集合。GeoJSON里的特征包含一个几何对象和其他属性,特征集合表示一系列特征。一个完整的GeoJSON数据结构总是一个(JSON术语里的)对象。在GeoJSON里,对象由名/值对--也称作成员的集合组成。对每个成员来说,名字总是字符串。成员的值要么是字符串、数字、对象、数组,要么是下面文本常量中的一个:"true","false"和"null"。数组是由值是上面所说的元素组成

MySQL空间数据存储及函数

除了简单的点、线、面,为了满足复杂的地理环境及地图业务,还会有多点(MultiPoint),多线(MultiLineString),多面(MultiPolygon),几何集合(GeometryCollection)等,熟悉json就可以快速的熟悉并应用geojson

3.格式化空间数据类型(geometry相互转换geojson)

数据库存储的空间数据通过可视化工具展示的明文结构为上面示例中所见,结构并不易于客户端解析,所以MySQL提供了几个空间函数用来解析及格式化空间数据,geojson是gis空间数据展示的标准格式,前端地图框架及后端空间分析相关框架都会支持geojson格式

MySQL空间数据存储及函数

示例:

准备示例数据

MySQL空间数据存储及函数

函数应用示例

1.查询绿藤气象监测点信息将geometry处理成geojson格式

执行sql:

select id,point_name,ST_ASGEOJSON(point_geom) as geojson from meteorological_point where id = 1

查询结果:

MySQL空间数据存储及函数

2.新增一个点位信息,客户端提交的点位geometry字符串需要使用ST_GEOMFROMTEXT函数处理才能插入,否则会报错

客户端提交点位信息

{
    "point_name":"新帅集团监测点",
    "geotext":"POINT(117.420671499 40.194914201)"}
}

错误示例:

insert into meteorological_point(point_name, point_geom) values("新帅集团监测点", "POINT(117.420671499 40.194914201)")
报错 1416 - Cannot get geometry object from data you send to the GEOMETRY field

正确插入sql:

insert into meteorological_point(point_name, point_geom) values("新帅集团监测点", ST_GEOMFROMTEXT("POINT(117.420671499 40.194914201)"))

3.新增点位,客户端提交点位格式为geojson格式,需要使用ST_GeomFromGeoJSON函数处理后进行插入

客户端提交点位信息

{
    "point_name":"民爆公司监测点",
    "geojson":"{"type": "Point", "coordinates": [117.410671499, 40.1549142015]}"}
}

插入SQL

insert into meteorological_point(point_name, point_geom) values("民爆公司监测点", ST_GeomFromGeoJSON("{\"type\": \"Point\", \"coordinates\": [117.410671499, 40.1549142015]}"))

空间数据格式化小结

mysql geometry数据存储需要对geometry文本或geojson进行函数处理后才能进行存储,否则会报错,查询时候使用格式化函数转成geojson方便服务端传输和客户端框架解析

二、空间分析

在上一部分介绍了空间函数存储,查询格式化处理相关的操作,了解空间数据结构及geojson,这一部分介绍空间数据处理函数的应用

1、根据点位及半径,生成缓冲区

MySQL空间数据存储及函数

在地图功能中,缓冲区是非常常见的功能,一来可以查看点线面一定范围类的覆盖区域,二来在一些分析场景中,已知一个位子坐标信息及缓冲半径,生成缓冲区作为查询条件进行地理搜索

SELECT ST_ASGEOJSON(ST_BUFFER(ST_GeomFromGeoJSON('${geojsonStr}'),${radius}))

SQL解读

调用方传来一个geojson字符串及半径(米),使用ST_GeomFromGeoJSONgeojson字符串处理成数据库中的geometry,再使用ST_BUFFER(geometry, 半径)s生成缓冲区空间数据,函数返回的格式也是geometry,所以在外面包一层ST_ASGEOJSON函数将返回结果处理成geojson,便于客户端读取及渲染

示例:

  • 有一个点位的geojson字符串为 "{"type": "Point", "coordinates": [117.410671499, 40.1549142015]}",缓冲半径50米(注意:ST_BUFFER()的参数地理信息及返回值均使用墨卡托坐标系,如非墨卡托坐标系的geojson,需使用工具类进行转换处理)
public class MercatorUtils {
    /**
     * 点位geojson转墨卡托
     *
     * @param point
     * @return
     */
    public static JSONObject point2Mercator(JSONObject point) {
        JSONArray xy = point.getJSONArray(COORDINATES);
        JSONArray mercator = lngLat2Mercator(xy.getDouble(0), xy.getDouble(1));
        point.put(COORDINATES, mercator);
        return point;
    }
    /**
     * 经纬度转墨卡托
     */
    public static JSONArray lngLat2Mercator(double lng, double lat) {
        double x = lng * 20037508.342789 / 180;
        double y = Math.log(Math.tan((90 + lat) * M_PI / 360)) / (M_PI / 180);
        y = y * 20037508.34789 / 180;
        JSONArray xy = new JSONArray();
        xy.add(x);
        xy.add(y);
        return xy;
    }
    
    /**
     * 墨卡托坐标系数据转普通坐标系
     */
    public static JSONObject mercatorPolygon2Lnglat(JSONObject polygon) {
        JSONArray coordinates = polygon.getJSONArray(COORDINATES);
        JSONArray xy = coordinates.getJSONArray(0);
        JSONArray ms = new JSONArray();
        for (int i = 0; i < xy.size(); i++) {
            JSONArray p = xy.getJSONArray(i);
            JSONArray m = mercator2lngLat(p.getDouble(0), p.getDouble(1));
            ms.add(m);
        }
        JSONArray newCoordinates = new JSONArray();
        newCoordinates.add(ms);
        polygon.put(COORDINATES, newCoordinates);
        return polygon;
    }
}

转换后的geojson就可以作为上面缓冲区的sql生成缓冲区空间数据了,生成的缓冲区数据也是墨卡托坐标系,需使用mercatorPolygon2Lnglat进行处理后返回给客户端,调用流程如下:

  • 客户端提交点位geojson及半径
  • 使用墨卡托工具类将点位geojson转换成墨卡托坐标系的geojson
  • 调用sql进行缓冲区生成
  • 返回值使用墨卡托工具类转换成mercatorPolygon2Lnglat返回给调用方

小结:

上面介绍如何使用mysql st_buffer函数生成缓冲区,实际操作起来经过我在研发中的应用是可行的,实际开发中还可以使用一些工具包来实现缓冲区生成,如geotools...

三、判断点位所在城市

  • 判断用户点位所在城市-客户端提交用户的定位信息,判断用户所在城市(使用ST_INTERSECTS()判断两个几何是否相交即可,返回0或1)
SELECT ST_INTERSECTS(ST_GeomFromGeoJSON('${geoJsonStrA}'), ST_GeomFromGeoJSON('${geoJsonStrB}'))

SQL解读:

使用格式化函数将geojson处理成函数支持的geomtry格式,使用ST_INTERSECTS进行判断即可

四、常用的空间函数

MySQL空间数据存储及函数

总结:

MySQL为空间数据的存储及分析提供了丰富的数据类型及函数,我们学习此类函数能够帮助我们更好的处理地理信息,使用前需要对坐标系、geojson相关知识进行了解,避免踩坑,如果有相关问题也可以在评论区交流,如有误区请指正。

到此这篇关于MySQL空间数据存储及函数的文章就介绍到这了,更多相关MySQL空间数据存储及函数内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

MySQL 相关文章推荐
MySQL 使用事件(Events)完成计划任务
May 24 MySQL
Mysql实现主从配置和多主多从配置
Jun 02 MySQL
MySQL单表千万级数据处理的思路分享
Jun 05 MySQL
Mysql 如何查询时间段交集
Jun 08 MySQL
如何搭建 MySQL 高可用高性能集群
Jun 21 MySQL
MySQL高级进阶sql语句总结大全
Mar 16 MySQL
MySQL提取JSON字段数据实现查询
Apr 22 MySQL
MySQL数据库 任意ip连接方法
May 20 MySQL
Mysql将字符串按照指定字符分割的正确方法
May 30 MySQL
MySQL8.0 Undo Tablespace管理详解
Jun 16 MySQL
MySQL示例讲解数据库约束以及表的设计
Jun 16 MySQL
Mysql数据库group by原理详解
Jul 07 MySQL
MySQL基础快速入门知识总结(附思维导图)
MySQL连接控制插件介绍
Sep 25 #MySQL
Mysql案例刨析事务隔离级别
Sep 25 #MySQL
MySQL定时备份数据库(全库备份)的实现
Sep 25 #MySQL
MySQL修改默认引擎和字符集详情
Sep 25 #MySQL
MySQL 用 limit 为什么会影响性能
Sep 15 #MySQL
一次MySQL启动导致的事故实战记录
Sep 15 #MySQL
You might like
PHP父类调用子类方法的代码例子
2014/04/09 PHP
php使用number_format函数截取小数的方法分析
2016/05/27 PHP
php中array_slice和array_splice函数解析
2016/10/18 PHP
thinkPHP线上自动加载异常与修复方法实例分析
2016/12/01 PHP
用php+ajax新建流程(请假、进货、出货等)
2017/06/11 PHP
TP5框架实现签到功能的方法分析
2020/04/05 PHP
jquery 子窗口操作父窗口的代码
2009/09/21 Javascript
jquery实现div拖拽宽度示例代码
2013/07/31 Javascript
随鼠标上下滚动的jquery代码
2013/12/05 Javascript
jQuery获取选中内容及设置元素属性的方法
2014/07/09 Javascript
jQuery实现仿新浪微博浮动的消息提示框(可智能定位)
2015/10/10 Javascript
详解Backbone.js框架中的模型Model与其集合collection
2016/05/05 Javascript
JS Canvas定时器模拟动态加载动画
2016/09/17 Javascript
Bootstrap模态窗口源码解析
2017/02/08 Javascript
官方推荐react-navigation的具体使用详解
2018/05/08 Javascript
vue.js内置组件之keep-alive组件使用
2018/07/10 Javascript
vue.js input框之间赋值方法
2018/08/24 Javascript
如何实现一个webpack模块解析器
2018/10/24 Javascript
微信小程序购物车、父子组件传值及calc的注意事项总结
2018/11/14 Javascript
node.js中ws模块创建服务端和客户端,网页WebSocket客户端
2019/03/06 Javascript
了解JavaScript中的选择器
2019/05/24 Javascript
JS学习笔记之闭包小案例分析
2019/05/29 Javascript
Vue form表单动态添加组件实战案例
2019/09/02 Javascript
vue+echarts+datav大屏数据展示及实现中国地图省市县下钻功能
2020/11/16 Javascript
[01:06]DOTA2小知识课堂 Ep.02 吹风竟可解梦境缠绕
2019/12/05 DOTA
python的Template使用指南
2014/09/11 Python
Python字典操作详细介绍及字典内建方法分享
2018/01/04 Python
python实现电脑自动关机
2018/06/20 Python
Python3.7中安装openCV库的方法
2018/07/11 Python
python用opencv批量截取图像指定区域的方法
2019/01/24 Python
Python使用while循环花式打印乘法表
2019/01/28 Python
Python+Pyqt实现简单GUI电子时钟
2021/02/22 Python
ABOUT YOU罗马尼亚:超过600个时尚品牌
2019/09/19 全球购物
自我鉴定范文
2013/11/10 职场文书
肖申克救赎观后感
2015/06/02 职场文书
值班管理制度范本
2015/08/06 职场文书