java实现搜索附近地点或人的功能
前言
当前大多数app都有查找附近的功能, 简单的有查找周围的运动场馆, 复杂的有滴滴, 摩拜查找周围的车辆. 本文主要阐述查找附近地点的一般实现.
方案比较
方案1 (性能还不错)
数据库直接存经纬度, 然后计算矩形边界值, 走索引查询
方案2 (还没试过)
将经纬度转换成 一个值, 然后进行比较查询 genhash
http://blog.csdn.net/newjueqi/article/details/18989867
方案3 (据说高性能, 性能怎样?待测试)
mongodb 地理类型, 高性能 http://www.tuicool.com/articles/Jfu6fy
sqlserver 地理数据 geography https://msdn.microsoft.com/en-us/library/ff929109.aspx
方案1的实现(本文主要阐述此方案)
实现环境: java+MySQL
场景模拟: 张三用户在成都天府五街查询周围10公里内的地点
1. 首先建立经纬度数据, 比如常见地点的经纬度数据库, 我这里是网上下载的一个shop_area 表数据,里面包含了一些常见地点的经纬度 ,如下图
2. 然后根据张三用户所在的经纬度, 以及他要查询的距离10公里, 得到查询范围矩形的四个顶点, 如下图: 
计算这四个点的 mybatis sql:
<select id="getCurrentLocationRectangle" parameterType="LocationFilter" resultType="LocationFilter">
SELECT
#{myLongitude} - #{distance} / ABS(COS(RADIANS(#{myLatitude})) * 69) AS LongitudeMin,
#{myLongitude} + #{distance} / ABS(COS(RADIANS(#{myLatitude})) * 69) AS LongitudeMax,
#{myLatitude} - (#{distance} / 69) AS LatitudeMin,
#{myLatitude} + (#{distance} / 69) AS LatitudeMax
</select>
3. 将刚才得到的矩形四个点的值代入如下sql 来进行经纬度查询过滤, 记得经纬度字段要建立索引
mybatis sql:
<select id="getUserNearbyAreaList" parameterType="com.anuo.app.modules.coach.entity.CoachFilter" resultType="ShopArea">
SELECT *
FROM (
SELECT
a.*,
GetDistance(#{myLatitude}, #{myLongitude}, a.lat, a.lng) AS distance
FROM shop_area a
WHERE
a.lat BETWEEN #{latitudeMin} AND #{latitudeMax}
AND a.lng BETWEEN #{longitudeMin} AND #{longitudeMax}
) z
<where>
<if test="distance > 0 ">
AND z.distance < #{distance}
</if>
</where>
ORDER BY z.distance
LIMIT #{pageStart},#{pageSize}
</select>
因为先是通过四个点走索引过滤的经纬度数据, 所以大大提升了效率. 并且将我们想要的10公里范围内的经纬度数据过滤了出来, 虽然多查询了点数据(见下图四个叉叉处), 见下面第四步, 将多余的剔除掉
4.上面sql中的 AND z.distance < #{distance} 即 AND z.distance 小于指定距离 #{distance}, 是将下图画叉叉部分的经纬度数据剔除,这些数据是多余的, 因为为我们要查询的是圆圈内的数据
这里用到了一个MySQL GetDistance 函数, 代码如下
DELIMITER $$
USE `anuoapp`$$
DROP FUNCTION IF EXISTS `GetDistance`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `GetDistance`(
myLatitude DECIMAL(11,8),#我当前位置的纬度
myLongitude DECIMAL(11,8),#我当前位置的经度
latitude DECIMAL(11,8),
Longitude DECIMAL(11,8)
) RETURNS DOUBLE
BEGIN
RETURN (
6371 * ACOS(
COS(RADIANS(myLatitude)) * COS(RADIANS(latitude)) * COS(RADIANS(Longitude) - RADIANS(myLongitude)) +
SIN(RADIANS(myLatitude)) * SIN(RADIANS(latitude))
)
);
END$$
DELIMITER ;
最后查询出张三在成都天府五街周围10公里内的地点
请求url: http://localhost:8080/v1/apiGetUserNearbyArea
请求体:
{
"Token":"6850d1c361e9478ca1e94496ec6b27f9",
"Version": "1.8.0",
"Entities": [
{
"myLatitude":30.54286,
"myLongitude":104.075569,
"distance":10,
"pageSize":10,
"pageNumber":1
}
],
"IsMobile": true,
"PageIndex": 1,
"IsInnerTest": true,
"IsGetIp": false,
"PageSize": 38,
"IsEncrypt": true,
"Parameters": {}
}
响应:
{
"success": true,
"totalRow": 11,
"entities": [
{
"id": "510122004",
"areaname": "中和街道",
"parentid": 510122,
"shortname": "中和街道",
"lng": "104.082375",
"lat": "30.559141",
"level": true,
"position": "tr_0 tr_510000 tr_510100 tr_510122",
"sort": 25,
"distance": 1.9241037391984028
},
{
"id": "510107063",
"areaname": "石羊场街道",
"parentid": 510107,
"shortname": "石羊场街道",
"lng": "104.048271",
"lat": "30.590687",
"level": true,
"position": "tr_0 tr_510000 tr_510100 tr_510107",
"sort": 12,
"distance": 5.925643914100619
},
{
"id": "510122122",
"areaname": "万安镇",
"parentid": 510122,
"shortname": "万安镇",
"lng": "104.112701",
"lat": "30.487444",
"level": true,
"position": "tr_0 tr_510000 tr_510100 tr_510122",
"sort": 18,
"distance": 7.114938271111233
},
{
"id": "510122120",
"areaname": "新兴镇",
"parentid": 510122,
"shortname": "新兴镇",
"lng": "104.149757",
"lat": "30.52656",
"level": true,
"position": "tr_0 tr_510000 tr_510100 tr_510122",
"sort": 21,
"distance": 7.332851650201873
},
{
"id": "510107007",
"areaname": "火车南站街道",
"parentid": 510107,
"shortname": "火车南站街道",
"lng": "104.082924",
"lat": "30.619801",
"level": true,
"position": "tr_0 tr_510000 tr_510100 tr_510107",
"sort": 7,
"distance": 8.5843717771867
}
]
}
完整源码见:
https://gitee.com/anuo/anuoapp
在此项目中搜索 apiGetUserNearbyArea 接口即可定位
完整数据库见:
https://pan.baidu.com/s/1o9lUJMU
java实现搜索附近地点或人的功能的更多相关文章
- SpringBoot入门教程(五)Java基于MySQL实现附近的人
“附近的人”这个功能估计都不陌生,与之类似的功能最开始是在各大地图应用上接触过,比如搜附近的电影院,附近的超市等等.然而真正让附近的人火遍大江南北的应该是微信"附近的人"这个功能, ...
- Java爬虫搜索原理实现
permike 原文 Java爬虫搜索原理实现 没事做,又研究了一下爬虫搜索,两三天时间总算是把原理闹的差不多了,基本实现了爬虫搜索的原理,本次实现还是俩程序,分别是按广度优先和深度优先完成的,广度优 ...
- 转:java开发的10位牛人
文章来自于:http://it.deepinmind.com/java/2014/04/10/top-10-java-people-you-should-know.html James Gosling ...
- 你知道吗?Java开发的10位牛人
James Gosling 1983年,Gosling获得了加州大学的计算机科学学士学位.1990年,他获得了卡内基梅隆大学的计算机科学博士学位,师从Bob Sproull.在攻读博士期间,他自己开发 ...
- Android进阶笔记03:Android应用中实现查看"附近的人"的功能
1. 要实现" 附近的人" 这功能,然后就研究了下: (1)首先要做的就是要获取到自己当前位置的经纬度(编程获取手机GPS定位模块的信息,进而获取自己当前位置的经纬度) (2)然后 ...
- Springboot+Vue实现仿百度搜索自动提示框匹配查询功能
案例功能效果图 前端初始页面 输入搜索信息页面 点击查询结果页面 环境介绍 前端:vue 后端:springboot jdk:1.8及以上 数据库:mysql 核心代码介绍 TypeCtrler .j ...
- 《Java中的自动装箱和拆箱功能.》
//Java中的自动装箱和拆箱功能. class AutoboxingUnboxing { public static void main(String[] args) { //直接把一个基本类型变量 ...
- Java 实现简答的单链表的功能
作者:林子木 博客网址:http://blog.csdn.net/wolinxuebin 參考网址:http://blog.csdn.net/sunsaigang/article/details/5 ...
- 使用 jquery 的 上传文件插件 uploadify 3.1 配合 java 来做一个简单的文件上次功能。并且在界面上有radio 的选择内容也要上传
使用 jquery 的 上传文件插件 uploadify 3.1 配合 java 来做一个简单的文件上次功能.并且在界面上有radio 的选择内容也要上传 uploadify 插件的 下载和文档地址 ...
随机推荐
- Abstract factory抽象工厂--对象创建型
意图: 提供一个创建一系列相关或者相互依赖对象的接口,而无需指定它们具体的类. 别名:Kit 补充: 抽象产品A : (产品A1 和产品 A2) 抽象产品B : ( 产品B1 和 产品B2) 一般情况 ...
- docker国内镜像拉取和镜像加速registry-mirrors配置修改
docker国内镜像拉取和镜像加速registry-mirrors配置修改 学习了:http://blog.csdn.net/u014231523/article/details/61197945 站 ...
- javascript 变量声明 和 作用域
变量的声明 1.变量声明具有提升机制,Javascript在执行时,会把所有的声明都提升到当前作用域前面. 先看一下下面的例子: (function(){ alert(b)//b is not def ...
- LeetCode 443. String Compression (压缩字符串)
题目标签:String 这一题需要3个pointers: anchor:标记下一个需要存入的char read:找到下一个不同的char write:标记需要存入的位置 让 read指针 去找到下一个 ...
- 万维网 WWW (World Wide Web)
万维网 WWW (World Wide Web)并非某种特殊的计算机网络.万维网是一个大规模的.联机式的信息储藏所.万维网用链接的方法能非常方便地从因特网上的一个站点访问另一个站点,从而主动地按需获取 ...
- [Unity 设计模式]IOC依赖倒置
1.前言 最近在看<游戏开发与设计模式>一书,看到控制反转设计模式,作者说:上层模块不应该依赖于下层模块,上层模块和下层模块都应该依赖于接口,这样能减少耦合.然后附带举了个例子,我觉得特别 ...
- How to create a random UUID in each Request's Headers
${=java.util.UUID.randomUUID()} is OK
- C#中的文件导出大全
s 得到 radiobuttonlist和CheckBoxList 选中值 得到radiobuttonlist 选中值:var CheckBoxList=document.all.optButtonL ...
- go语言笔记——append底层实现和Cpp vector无异,只是有返回值,double后返回了新的vector地址而已
切片的复制与追加 如果想增加切片的容量,我们必须创建一个新的更大的切片并把原分片的内容都拷贝过来.下面的代码描述了从拷贝切片的 copy 函数和向切片追加新元素的 append 函数. 示例 7.12 ...
- 8.3 TCPIP协议族
接下来我们要学习的内容是TCP/IP协议族.TCP/IP协议族在网络系统中是非常重要的.这一个协议族当中牵涉到许许多多的我们平常所用到的协议.TCP/IP呢它也有分层模型.然后我们讲到的就是三方面的内 ...