mysql利用geometry字段在laravel框架下,来完成空间类查询

在做一项目时,用到经纬度坐标,经过多次百度,找到了geometry这个字段,用这个字段,MYSQL提供了很方便的函数,比如查询两个点之间的距离,查询距离这个点多少米的所有点,查询距离这个点最近的几个点,然后用laravel写了几个功能。

参考链接:

建表

表test

###表point

其中,gis的类型是geometry类型的,用来储存经纬度,geohash是利用gis经过哈希算法得到的字符串,利用此字符串比较效率更高,具体见文章顶部连接,它的结构如下:

插入数据

此处只说laravel的插入方法,具体sql命令详见文章顶链接

1
2
3
4
5
test = new Test();
test->longitude = 118.0065880;
test->latitude = 36.8197360;
test->save();
DB::statement("update test set gis = geomfromtext('point(test->longitude test->latitude)') where id = $test->id");

Test是laravel的一个模型,对应test数据表,先把经纬度赋值给test的longitude和latitude字段,然后再插入gis字段,因为`geomfromtext()`是MYSQL提供的方法,所以不能直接`test->gis = geomfromtext(‘point($test->longitude $test->latitude)’);`,而是用DB的statement方法来运行原生SQL命令。

查询两点的距离

point

id name gis geohash longitude latitude
1 淄博客运总站 POINT(118.007117 36.793214) wwecm640 118.007117 36.793214

test

id gis geohash longitude latitude
12 POINT(117.035999 36.687248) wwe0xnxn 117.035999 36.687248

代码如下

1
2
3
4
5
6
7
8
9
10
11
distance \= DB::select('select floor(st\_distance\_sphere(
(select gis from test where id = ?),gis
)) distance from point where id= ?',[12,1]);
dd(distance);
/*查询结果
array:1 [▼
0 => {#184 ▼
+"distance": 87331.0
}
]
*/

查询到这个点距离最短的点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
point\_gis \= Test::find(12)\->gis;
point\= DB::select('select *,floor(st_distance_sphere(?,gis)) distance from point order by distance asc',[point\_gis\])\[0\];
dd(point);


/*查询结果
{#185 ▼
+"id": 1
+"name": "淄博客运总站"
+"gis": b"\x00\x00\x00\x00\x01\x01\x00\x00\x00©Å▄ÜtÇ]@[]N\têeB@"
+"geohash": "wwecm640"
+"longitude": 118.007117
+"latitude": 36.793214
+"distance": 2946.0
}
*/

原理:$point_gis获取到了test表中 id为12的gis字段的值 利用SQL的空间距离查询函数st_distance_sphere(?,?)在point表中查询每个点到 test表中id为12的点的距离,并按距离升序排列。floor()是把计算出的距离取整。

评论