MySQL 5.7 地理空间匹配适配

文章目录

  • [一. 背景](#一. 背景)
  • [二 . 实操](#二 . 实操)
    • [1.MySQL 5.7 环境部署(Docker 方式)](#1.MySQL 5.7 环境部署(Docker 方式))
      • [1.1 部署脚本优化](#1.1 部署脚本优化)
      • [1.2 部署注意事项](#1.2 部署注意事项)
    • [2. 地理空间知识说明](#2. 地理空间知识说明)
      • [2.1 地理空间字段类型](#2.1 地理空间字段类型)
      • [2.2 地理函数](#2.2 地理函数)
    • [3.地理匹配实战:数据库表设计与 SQL 操作](#3.地理匹配实战:数据库表设计与 SQL 操作)
      • [3.1 表结构设计](#3.1 表结构设计)
      • [3.2 数据插入(场景示例)](#3.2 数据插入(场景示例))
      • [3.3 地理匹配查询(核心逻辑)](#3.3 地理匹配查询(核心逻辑))

一. 背景

为实现警情案例的区域化管理与精准溯源,需完成 "经纬度警情案例与围栏区域的空间匹配" 核心任务:基于含精准经纬度坐标的警情数据,通过空间几何计算判定每个警情所属的预设围栏区域,最终输出 "警情信息 - 经纬度 - 围栏标识" 的关联整合结果,为后续区域警情分析、资源调度提供数据支撑。

输入数据说明

警情案例数据:

含具体警情相关信息及对应的经纬度坐标(示例数据如下)

id longitude latitude incident_content
1 113.886000 22.558000 壹方城购物中心前发生两车追尾事故,造成交通拥堵,需交警前往处理
2 113.868000 22.578000 西乡地铁站B出口发生盗窃案件,嫌疑人已逃跑,需要民警介入调查
3 113.810000 22.639000 T3航站楼2号门有旅客突发晕倒,需要医疗救助
4 113.915000 22.578000 新安公园旁餐饮店发生小火情,已初步控制,需要消防检查
5 113.880000 22.561000 宝安中心区夜间施工噪声扰民,居民多次投诉无果
6 113.880500 22.583200 宝安大仟里夜间施工噪声扰民,居民多次投诉无果

围栏数据:

包含围栏唯一名称及区域范围定义,支持 圆形围栏多边形围栏 两种类型(字段互斥,同一围栏仅对应一种类型),示例如下:

name geofence_point radius geofence_polygon
宝安大仟里商圈 POINT(113.8781 22.5806) 500
西丽国际创新谷商圈 POINT(113.9472 22.5925) 600
高新园万象城商圈 POINT(113.9398 22.5412) 800
宝安中心区 POLYGON((113.875 22.556,113.885 22.556,113.885 22.566,113.875 22.566,113.875 22.556))
西乡街道 POLYGON((113.86 22.575,113.87 22.575,113.87 22.585,113.865 22.588,113.86 22.585,113.86 22.575))
宝安机场 POLYGON((113.805 22.635,113.815 22.635,113.815 22.645,113.81 22.648,113.805 22.645,113.805 22.635))
新安街道 POLYGON((113.91 22.572,113.92 22.572,113.92 22.582,113.915 22.584,113.91 22.582,113.91 22.572))

预期输出结果

核心匹配规则

  1. 优先保障匹配唯一性:若单个警情同时满足多个围栏的判定条件(极端重叠场景),按 "多边形围栏优先于圆形围栏""小范围围栏优先于大范围围栏" 的优先级输出唯一结果;
  2. 无匹配处理:若警情坐标未落在任何预设围栏内,围栏名称字段留空。

预期输出结果

输出整合后的结构化数据,包含警情全量信息、经纬度及对应围栏名称,示例如下:

id longitude latitude incident_content name
6 113.880500 22.583200 宝安大仟里夜间施工噪声扰民,居民多次投诉无果 宝安大仟里商圈
5 113.880000 22.561000 宝安中心区夜间施工噪声扰民,居民多次投诉无果 宝安中心区
2 113.868000 22.578000 西乡地铁站B出口发生盗窃案件,嫌疑人已逃跑,需要民警介入调查 西乡街道
3 113.810000 22.639000 T3航站楼2号门有旅客突发晕倒,需要医疗救助 宝安机场
4 113.915000 22.578000 新安公园旁餐饮店发生小火情,已初步控制,需要消防检查 新安街道
1 113.886000 22.558000 壹方城购物中心前发生两车追尾事故,造成交通拥堵,需交警前往处理

二 . 实操

1.MySQL 5.7 环境部署(Docker 方式)

1.1 部署脚本优化

优化说明:修复日志查看容器名不一致问题,增加目录提前创建逻辑,避免挂载失败,同时优化脚本可读性和可维护性。

sh 复制代码
# 1. 创建相关目录(避免挂载时权限或目录不存在问题)
mkdir -p /home/mysql/{conf,data,logs}
cd /home/mysql

# 2. 编写 docker-compose 配置文件
cat > /home/mysql/docker-compose.yml << EOF
version: '3'
services:
  scs-mysql: 
    image: mysql:5.7.30
    hostname: scs-mysql
    container_name: scs-mysql
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - TZ=Asia/Shanghai
    restart: always
    healthcheck:
      test: ["CMD", "mysqladmin" ,"ping", "-h", "localhost", "-uroot", "-p123456"]
      interval: 5s
      timeout: 1s
      retries: 10
    privileged: true
    ports:
      - 3306:3306
    volumes:
      - $PWD/data:/var/lib/mysql
      - $PWD/logs:/var/log/mysql
      - $PWD/conf/my.cnf:/etc/mysql/my.cnf
    command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci','--default-time-zone=+08:00']
    entrypoint: bash -c "chown -R mysql:mysql /var/log/mysql && exec /entrypoint.sh mysqld"

EOF

# 3. 编写 MySQL 配置文件
cat > /home/mysql/conf/my.cnf << EOF
!includedir /etc/mysql/conf.d/ 
!includedir /etc/mysql/mysql.conf.d/
[client]
default-character-set=utf8

[mysql]
default-character-set=utf8

[mysql.server]
default-character-set=utf8

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time-zone=+08:00
max_connections=1024
slow_query_log=1
long_query_time=2
slow_query_log_file=/var/log/mysql/slow.log
log_error=/var/log/mysql/error.log
EOF


# 4. 启动容器并查看日志
docker-compose up -d
docker logs -f scs-mysql  

1.2 部署注意事项

  1. 确保服务器已安装 Docker 和 Docker Compose;
  2. 若 3306 端口已被占用,可修改 ports 中的宿主端口(如 3307:3306);
  3. 部署完成后,可通过 mysql -h 127.0.0.1 -uroot -p123456 验证连接。

2. 地理空间知识说明

2.1 地理空间字段类型

分类 类型 描述 示例(WKT格式)
多边形类型 POLYGON 一个由封闭边界定义的多边形区域。 POLYGON((0 0,10 0,10 10,0 10,0 0))
单值类型 POINT 一个坐标点。 POINT(121.213342 31.234532)
集合类型 MULTIPOLYGON(暂时不用) 多个多边形的集合。 MULTIPOLYGON(((0 0, 100 0, 100 100, 0 100, 0 0), (20 20, 80 20, 80 80, 20 80, 20 20)), ((200 0, 250 0, 250 50, 200 50, 200 0)))

2.2 地理函数

函数类别 函数示例 用途说明
数据转换 ST_GeomFromText('POINT(1 2)') 将文本(WKT格式)转换为空间数据。
ST_AsText(geom_column) 将空间数据转换回可读的文本格式。
空间关系判断 ST_Within(point, polygon) 判断一个点是否在一个多边形内。
ST_Contains(polygon, point) 判断一个多边形是否包含一个点。
空间计算 ST_Distance_Sphere(point1, point2) 计算两点在地球球面上的近似距离(单位:米)。

3.地理匹配实战:数据库表设计与 SQL 操作

3.1 表结构设计

sql 复制代码
-- 区域围栏表
drop table if exists mcp_geofence_xxxx;
CREATE TABLE `mcp_geofence_xxxx` (
  `name` VARCHAR(100) comment '围栏名称',
  `geofence_point` POINT  NULL comment '圆心坐标',
  `radius` DOUBLE NULL comment '半径(单位:米)',
  `geofence_polygon` POLYGON NULL comment '边界'
);
-- SPATIAL KEY `idx_geofence` (`geofence_point`),
-- SPATIAL KEY `idx_geofence` (`geofence_polygon`)
-- 由于空间索引不允许为空,所以删除

-- 警情表
drop table if exists mcp_police_test;
create TABLE mcp_police_test (
    id INT PRIMARY KEY AUTO_INCREMENT,
    longitude DECIMAL(10,6) NOT NULL COMMENT '经度',
    latitude DECIMAL(10,6) NOT NULL COMMENT '纬度',
    incident_content TEXT NOT NULL COMMENT '警情内容',
    INDEX idx_location(longitude, latitude)
) COMMENT='警情信息表';

3.2 数据插入(场景示例)

sql 复制代码
-- 圆形
-- 宝安大仟里商圈(大约位置:22.5806° N, 113.8781° E)
INSERT INTO `mcp_geofence_xxxx` (`name`, `geofence_point`, `radius`) 
VALUES ('宝安大仟里商圈', ST_GeomFromText('POINT(113.8781 22.5806)'), 500);

-- 西丽国际创新谷商圈(大约位置:22.5925° N, 113.9472° E)
INSERT INTO `mcp_geofence_xxxx` (`name`, `geofence_point`, `radius`) 
VALUES ('西丽国际创新谷商圈', ST_GeomFromText('POINT(113.9472 22.5925)'), 600);

-- 高新园万象城商圈(大约位置:22.5412° N, 113.9398° E)
INSERT INTO `mcp_geofence_xxxx` (`name`, `geofence_point`, `radius`) 
VALUES ('高新园万象城商圈', ST_GeomFromText('POINT(113.9398 22.5412)'), 800);

-- 多边形
INSERT INTO mcp_geofence_xxxx (name, geofence_polygon) VALUES ('宝安中心区',ST_GeomFromText('POLYGON((113.875 22.556, 113.885 22.556, 113.885 22.566, 113.875 22.566, 113.875 22.556))')),('西乡街道',ST_GeomFromText('POLYGON((113.860 22.575, 113.870 22.575, 113.870 22.585, 113.865 22.588, 113.860 22.585, 113.860 22.575))')),('宝安机场',ST_GeomFromText('POLYGON((113.805 22.635, 113.815 22.635, 113.815 22.645, 113.810 22.648, 113.805 22.645, 113.805 22.635))')),('新安街道',ST_GeomFromText('POLYGON((113.910 22.572, 113.920 22.572, 113.920 22.582, 113.915 22.584, 113.910 22.582, 113.910 22.572))'));

SELECT name, ST_AsText(geofence_point), radius,ST_AsText(geofence_polygon) AS point_text FROM mcp_geofence_xxxx ;



-- 插入6条分布在宝安区不同地点的警情数据
INSERT INTO mcp_police_test 
(longitude, latitude, incident_content) VALUES

(113.886, 22.558, 
 '壹方城购物中心前发生两车追尾事故,造成交通拥堵,需交警前往处理'),

-- 2. 西乡街道 - 治安事件
(113.868, 22.578,
 '西乡地铁站B出口发生盗窃案件,嫌疑人已逃跑,需要民警介入调查'),

-- 3. 宝安机场 - 紧急求助
(113.810, 22.639,
 'T3航站楼2号门有旅客突发晕倒,需要医疗救助'),

-- 4. 新安街道 - 消防警情
(113.915, 22.578,
 '新安公园旁餐饮店发生小火情,已初步控制,需要消防检查'),

-- 5. 宝安中心区 - 噪声投诉
(113.880, 22.561,
 '宝安中心区夜间施工噪声扰民,居民多次投诉无果'),
-- 6. 宝安大仟里 - 噪声投诉
(113.8805,22.5832, '宝安大仟里夜间施工噪声扰民,居民多次投诉无果');

3.3 地理匹配查询(核心逻辑)

sql 复制代码
drop table if exists mcp_police_result; 
  create table mcp_police_result SELECT 
      pi.id,
      pi.incident_content,
      pi.longitude,
      pi.latitude,
      gf.name
  FROM 
      mcp_police_test pi
  LEFT JOIN 
      mcp_geofence_xxxx gf ON (
        (gf.geofence_polygon IS NOT NULL 
         and ST_Within(ST_GeomFromText(CONCAT('POINT(', pi.longitude, ' ', pi.latitude, ')')),gf.geofence_polygon))
        OR
        (gf.geofence_point IS NOT NULL AND gf.radius IS NOT NULL
              AND ST_Distance_Sphere(
                  ST_GeomFromText(CONCAT('POINT(', pi.longitude, ' ', pi.latitude, ')')),
                  gf.geofence_point
              ) <= gf.radius)
      );

SELECT * from mcp_police_result;
相关推荐
VX:Fegn08957 小时前
计算机毕业设计|基于ssm + vue超市管理系统(源码+数据库+文档)
前端·数据库·vue.js·spring boot·后端·课程设计
chipsense7 小时前
电流传感器型号从数据库查询并排序输出到网页的方法
数据库·php·传感器·霍尔电流传感器
踢足球09297 小时前
寒假打卡:2026-01-28
数据库·oracle
麦聪聊数据7 小时前
智慧医疗数据互联互通:使用 QuickAPI 构建实时诊疗数据交换层
数据库·sql·安全
风吹落叶花飘荡7 小时前
2026年mysql数据库迁移(全流程)
数据库·mysql
2301_822382767 小时前
Python上下文管理器(with语句)的原理与实践
jvm·数据库·python
m0_748229997 小时前
Laravel8.X核心功能全解析
开发语言·数据库·php
液态不合群8 小时前
【面试题】MySQL 的索引下推是什么?
数据库·mysql
2301_790300968 小时前
Python深度学习入门:TensorFlow 2.0/Keras实战
jvm·数据库·python
Code blocks9 小时前
SpringBoot从0-1集成KingBase数据库
数据库