当前位置:首页 > AI技术 > 正文内容

如何在Think中计算两点 间的地理距离 Dbraw执行GIS空间函数最佳践|Duuu笔记

admin2周前 (04-04)AI技术19

PHP进阶技巧:本文深入解析

行,但需数据库支持GIS函数、函数名正确、坐标系一致;MySQL用ST_Distance_Sphere,PostgreSQL用ST_DistanceSphere,字段须为POINT类型且坐标顺序为经度纬度,推荐参数绑定防注入并确保走空间索引。

ThinkPHP里直接用

Db::raw

调GIS函数算距离行不行?

行,但得看数据库是否支持、函数名是否匹配、坐标系是否一致。MySQL 5.7+、PostgreSQL + PostGIS 都可以,SQLite 基本不行;

Db::raw

只是把字符串原样塞进 SQL,不校验语法也不转义,写错就报错。

常见错误现象:

SQLSTATE[42000]: Syntax error or access violation

FUNCTION xxx does not exist

,基本都是函数名拼错、没开启空间扩展、或者字段类型不是

POINT

MySQL 必须用

ST_Distance_Sphere

(推荐)或

ST_Distance

(平面近似,精度差)

PostgreSQL + PostGIS 要用

ST_DistanceSphere

,注意大小写和参数顺序

字段必须是

POINT

类型,且用

POINT(longitude latitude)

格式存(经度在前,纬度在后)

别直接拼字符串,用

Db::raw("ST_Distance_Sphere(location, POINT(?, ?))", [$lng, $lat])

这种带参数绑定的方式,防注入也保类型

为什么

ST_Distance_Sphere

haversine

手动算更可靠?

因为 MySQL 内置函数自动处理了椭球模型(WGS84),而手写 haversine 是球面近似,10km 以内误差可能不到 10 米,但跨纬度大范围(比如哈尔滨到三亚)偏差能到百米级。而且

ST_Distance_Sphere

能走空间索引(如果字段加了

SPATIAL

索引),查询快几倍。

ST_Distance_Sphere

返回单位是「米」,不用再乘 1000 或除 1000

必须确保两个

POINT

在同一坐标系(通常是 EPSG:4326),否则结果无意义

如果用

ST_Distance

(不带 Sphere),它算的是平面欧氏距离,单位是「度」,完全不能直接当公里用

ThinkPHP 的

whereRaw

fieldRaw

才真正需要

Db::raw

,单纯

select

字段里用就足够

where

条件里用

Db::raw

算距离并过滤,怎么写才不出错?

重点不是“怎么写”,而是“怎么避免全表扫描”。只要用了

ST_Distance_Sphere

就没法走 B-tree 索引,但可以先用矩形范围粗筛,再精算。

Sheet+

Excel和GoogleSheets表格AI处理工具

下载

PHP免费学习笔记(深入)

”;

先用

ST_Contains(ST_MakeEnvelope(...), location)

或简单

lng BETWEEN ? AND ? AND lat BETWEEN ? AND ?

锁定候选集

再在

whereRaw

里用

ST_Distance_Sphere

做最终过滤,例如:

whereRaw('ST_Distance_Sphere(location, POINT(?, ?))

别在

order by

里直接写

Db::raw('ST_Distance_Sphere(...)')

排序——除非数据量极小,否则慢得明显

如果真要按距离排序,考虑加个虚拟列(MySQL 5.7+)或用子查询缓存距离值

PostgreSQL + PostGIS 场景下,

Db::raw

要注意什么?

PostGIS 函数名首字母大写(

ST_DistanceSphere

),参数顺序是

(geom1, geom2)

,且要求 geometry 类型必须显式指定 SRID,否则返回

null

建表时字段定义得写成

location GEOGRAPHY(POINT, 4326)

,不能只写

GEOMETRY

查询时用

ST_SetSRID(ST_MakePoint(?, ?), 4326)

构造目标点,否则

ST_DistanceSphere

拒绝计算

ThinkPHP 默认 PDO 不启用

PDO::ATTR_EMULATE_PREPARES = false

,PostgreSQL 对二进制协议敏感,建议显式配置

错误信息像

function st_distancesphere(geography, geography) does not exist

,八成是 SRID 没对齐或类型不匹配

地理距离计算最麻烦的从来不是写那一行

Db::raw

,而是确认数据库版本、空间类型定义、坐标系一致性,以及有没有悄悄绕过索引。漏查任意一项,线上查一次就卡三秒。

相关文章

【深度学习】Java DL4J 2024年度技术总结

一、Java DL4J深度学习概述 1.1 DL4J框架简介 1.2 与其他深度学习框架的比较 1.3 DL4J 的优势 1.3.1 与 Java 生态系统的无...

什么是LLM?看这一篇就够了!

一、全套AGI大模型学习路线 AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能! 二、640套AI大模型报告合集 这套包含640份报告的合集,涵盖了AI大...

使用 ESP

针对该分类问题,我们使用了 Kaggle 手势识别数据集 中的一个开源数据集。原始数据集包括 10 个类别,我们只使用了其中 6 个。这些类别更容易识别,且日常生活中更有用,如...

一文讲清神经网络、BP神经网络、深度学习的关系

人工神经网络中的顶级代表。往往说《神经网络》就是指《BP神经网络》。 大家研究着各种神经网络,研究得不亦乐乎, 来了两个家伙Romelhart 和Mcclelland,...

前端开发实战详解:骡子快跑怎么注册账号 骡子快跑账号注册流程最佳实践|Duuu笔记

骡子快跑注册仅需1分钟,但激活码需从Discord指定频道获取,输错3次将锁账户24小时;积分与注册邮箱强绑定且不可更换;部分地区即使注册成功也无法运行Agent。 ☞☞☞AI 智能聊天, 问答助手...

从入门到精通:前端开发之骡子快跑支持热点借势吗 骡子快跑节日营销文案生成|Duuu笔记

骡子快跑平台提供五步节日营销文案生成路径:一、调用内置32个节日模板库;二、输入热点事件触发动态生成;三、绑定自有素材库实现个性化延展;四、多角色视角协同输出;五、接入微信生态直发并校验合规性。 ☞...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。