
文章目录
- [一. 背景](#一. 背景)
- [二 . 实操](#二 . 实操)
-
- [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)) |
预期输出结果
核心匹配规则
- 优先保障匹配唯一性:若单个警情同时满足多个围栏的判定条件(极端重叠场景),按 "多边形围栏优先于圆形围栏""小范围围栏优先于大范围围栏" 的优先级输出唯一结果;
- 无匹配处理:若警情坐标未落在任何预设围栏内,围栏名称字段留空。
预期输出结果
输出整合后的结构化数据,包含警情全量信息、经纬度及对应围栏名称,示例如下:
| 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 部署注意事项
- 确保服务器已安装 Docker 和 Docker Compose;
- 若 3306 端口已被占用,可修改
ports中的宿主端口(如3307:3306); - 部署完成后,可通过
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;
