简介
现在几乎所有的O2O应用中都会存在“按范围搜素、离我最近、显示距离”等等基于位置的交互,那这样的功能是怎么实现的呢?本文提供的实现方式,适用于所有数据库。
实现
为了方便下面说明,先给出一个初始表结构,我使用的是MySQL:
CREATE TABLE `customer` ( `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主键', `name` VARCHAR(5) NOT NULL COMMENT '名称', `lon` DOUBLE(9,6) NOT NULL COMMENT '经度', `lat` DOUBLE(8,6) NOT NULL COMMENT '纬度', PRIMARY KEY (`id`) ) COMMENT='商户表' CHARSET=utf8mb4 ENGINE=InnoDB ;
实现过程主要分为四步:
1. 搜索
在数据库中搜索出接近指定范围内的商户,如:搜索出1公里范围内的。
2. 过滤
搜索出来的结果可能会存在超过1公里的,需要再次过滤。如果对精度没有严格要求,可以跳过。
3. 排序
距离由近到远排序。如果不需要,可以跳过。
4. 分页
如果需要2、3步,才需要对分页特殊处理。如果不需要,可以在第1步直接SQL分页。
第1步数据库完成,后3步应用程序完成。
step1 搜索
搜索可以用下面两种方式来实现。
区间查找
customer表中使用两个字段存储了经度和纬度,如果提前计算出经纬度的范围,然后在这两个字段上加上索引,那搜索性能会很不错。
那怎么计算出经纬度的范围呢?已知条件是移动设备所在的经纬度,还有满足业务要求的半径,这很像初中的一道平面几何题:给定圆心坐标和半径,求该圆外切正方形四个顶点的坐标。而我们面对的是一个球体,可以使用spatial4j来计算。
com.spatial4j
spatial4j
0.5
// 移动设备经纬度
double lo