java 实现微信搜索附近人功能

标签: java 微信 搜索 | 发表时间:2015-03-25 18:07 | 作者:1028826685
出处:http://www.iteye.com

最近给andorid做后台查询数据功能,有一个需求是模仿微信的查找附近人功能。 数据库中存储每个用户的经纬度信息及用户信息,通过当前用户传递过来的经纬度查询这个用户半径N公里以内的用户信息。   

数据库表结构

 

表信息 表名 Mobile_User
mu_id 自增,主键
mu_u_id 用户表的ID 外键
mu_longitud 精度
mu_latitude 纬度

(还有其他的一些信息,这里就列举4个字段足矣)

 

 

首先需要一个方法,是把传递过来的经纬度按照半径N公里扩散,找出距离中心经纬度N公里的上下左右经纬度值。效果如图

尴尬 随手画的  勿喷

 

以中心生成经纬度时 正上方和正下方的精度是不变的,只有纬度变化。 生成左右时道理一样,只有精度变化,纬度是不变的。

所以只需要生成上下的纬度,左右的精度就可以了。

参考了网上的文章, http://digdeeply.info/archives/06152067.html 这篇文章是用PHP实现的经纬度查询。修改成java的 代码如下

/**
     * 生成以中心点为中心的四方形经纬度
     * 
     * @param lat 纬度
     * @param lon 精度
     * @param raidus 半径(以米为单位)
     * @return
     */ 
    public static double[] getAround(double lat, double lon, int raidus) { 
 
        Double latitude = lat; 
        Double longitude = lon; 
 
        Double degree = (24901 * 1609) / 360.0; 
        double raidusMile = raidus; 
 
        Double dpmLat = 1 / degree; 
        Double radiusLat = dpmLat * raidusMile; 
        Double minLat = latitude - radiusLat; 
        Double maxLat = latitude + radiusLat; 
 
        Double mpdLng = degree * Math.cos(latitude * (Math.PI / 180)); 
        Double dpmLng = 1 / mpdLng;              
        Double radiusLng = dpmLng * raidusMile;  
        Double minLng = longitude - radiusLng;   
        Double maxLng = longitude + radiusLng;   
        return new double[] { minLat, minLng, maxLat, maxLng }; 
    }

 

这样四周的经纬度都已经生成了。    
下一步是查询数据库中和四周经纬度匹配的数据。 如果数据量很大的话会很耗时间,而且会很消耗流量。所以需要用到分页查询 

代码如下

 

@RequestMapping(params = "doGetQuserNearList")
@ResponseBody
public JSONObject doGetQuserNearList( HttpServletRequest request) {
    JSONObject jsonObject=new JSONObject();
    String km=request.getParameter("km");//搜索范围  这里以米为单位
    String useridString=request.getParameter("userid");
    String precision=request.getParameter("precision");
    String latitude=request.getParameter("latitude");
    String rows=request.getParameter("rows");
    String page=request.getParameter("page");
    try {
       
        if("".equals(useridString)||useridString==null){
            jsonObject.put("status", "0");
            jsonObject.put("msg", "用户id不能为空");
            return jsonObject;
        }
       
        Session session= memberService.getSession();
        Query query=null;
     
     org.hibernate.SQLQuery sqlQuery= session.createSQLQuery("select * from q_member  where latitude <> 0 "
                + "and _precision > :left_lat "
                + "and _precision < :right_lat "
                + "and latitude > :down_lon  "
                + "and latitude < :top_lon  "
                + "and id <> :userid "
                +" order by ACOS(SIN((:lat * 3.1415) / 180 ) * SIN((latitude * 3.1415) / 180 )+COS((:lat * 3.1415) / 180 )*COS((latitude * 3.1415) / 180 )*COS((:lon * 3.1415) / 180 - (_precision * 3.1415) / 180 ) ) * 6380 asc limit :start,:size");
         double[] lalon=Location.getAround(Double.valueOf(latitude), Double.valueOf(precision), Integer.valueOf(km));
       
         sqlQuery.setParameter("left_lat", lalon[1]);   
         sqlQuery.setParameter("right_lat", lalon[3]);
         sqlQuery.setParameter("down_lon", lalon[0]);
         sqlQuery.setParameter("top_lon", lalon[2]);
         
         sqlQuery.setParameter("lat", latitude);
         sqlQuery.setParameter("lon", precision);
         sqlQuery.setParameter("start", Integer.valueOf(page)-1);
         sqlQuery.setParameter("size", Integer.valueOf(rows));
         sqlQuery.setParameter("userid", useridString);
         
            java.util.List<MemberEntity> memberEntities=sqlQuery.addEntity(MemberEntity.class).list();
        
        //循环计算相对距离
        for(MemberEntity memberEntity:memberEntities){
       
            memberEntity.setDistance(Location.distance(Double.valueOf(latitude), Double.valueOf(precision), Double.valueOf(memberEntity.getLatitude()), Double.valueOf(memberEntity.getPrecision())));
        }
       
    
        jsonObject.put("status", "1");
        jsonObject.put("msg", memberEntities);
       
    } catch (Exception e) {
        e.printStackTrace();
        message = "获取失败";
        jsonObject.put("status", "0");
        jsonObject.put("msg", message);
        throw new BusinessException(e.getMessage());
    }
   
    return jsonObject;
}

 

我用的是Hibernate框架,  sql语句计算了每条数据和中心经纬度的距离并且以最近进行排序。  sql语句是根据下面的方法演变而来
方法是计算两个经纬度之间的直线距离。

 

/**
     * 计算中心经纬度与目标经纬度的距离(米)
     * 
     * @param centerLon
     *            中心精度
     * @param centerLan
     *            中心纬度
     * @param targetLon
     *            需要计算的精度
     * @param targetLan
     *            需要计算的纬度
     * @return 米
     */ 
    private static double distance(double centerLon, double centerLat, double targetLon, double targetLat) { 
 
        double jl_jd = 102834.74258026089786013677476285;// 每经度单位米; 
        double jl_wd = 111712.69150641055729984301412873;// 每纬度单位米; 
        double b = Math.abs((centerLat - targetLat) * jl_jd); 
        double a = Math.abs((centerLon - targetLon) * jl_wd); 
        return Math.sqrt((a * a + b * b)); 
    }

 

这样既实现了分页处理,又实现了每条数据的经纬度与中心经纬度的直线距离(以米为单位)。   
 

 

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [java 微信 搜索] 推荐:

java 实现微信搜索附近人功能

- - Java - 编程语言 - ITeye博客
最近给andorid做后台查询数据功能,有一个需求是模仿微信的查找附近人功能. 数据库中存储每个用户的经纬度信息及用户信息,通过当前用户传递过来的经纬度查询这个用户半径N公里以内的用户信息. 表名 Mobile_User. (还有其他的一些信息,这里就列举4个字段足矣). 首先需要一个方法,是把传递过来的经纬度按照半径N公里扩散,找出距离中心经纬度N公里的上下左右经纬度值.

elasticsearch RESTful搜索引擎-(java jest 使用[入门])

- - zzm
elasticsearch简称ES. 好吧下面我介绍下jest(第三方工具),个人认为还是非常不错的...想对ES用来更好,多多研究源代码吧...迟点,会写一些关于ES的源代码研究文章,现在暂时还是入门的阶段.哈..(不敢,不敢). 它是ES的java客户端,基于http restful.... jest是开源的....其他就不清楚了,看源代码吧..哈..

【技术贴】9个基于Java的搜索引擎框架

- - 行业应用 - ITeye博客
9个基于Java的搜索引擎框架. 1.Java全文搜索引擎框架Lucene. 毫 无疑问,Lucene是目前最受欢迎的Java全文搜索框架,准确地说,它是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引 擎. Lucene为开发人员提供了相当完整的工具包,可以非常方便地实现强大的全文检索功能.

微信做搜索:未来是「微信网」还是「万维网」?

- - 钛媒体:网罗天下创新事
看到微信要做搜索的新闻其实并不惊讶,毕竟近几个月来微信一直「小动作」不断,3月份微信指数推出之后,广告主在微信平台投放广告时就会问「你们有没有基于微信热词的广告报价啊」,似乎预示着一些零碎的出招结束之后,微信还是会踏入移动搜索领域. 动作很快,4月24日,搜狗发布公布2017年Q1财报的同一天,腾讯的微信事业群内部架构作了一些调整,微信事业群下成立搜索应用部.

java给微信发送get和post请求

- - CSDN博客推荐文章
现在做微信订阅号、微信公众号,微信企业号都需要开发者给微信服务器发送get或post请求. 具体发送get或post请求源码如下:. * 向指定URL发送GET方法的请求. 请求参数,请求参数应该是 name1=value1&name2=value2 的形式. * @return URL 所代表远程资源的响应结果.

微信开发处理超时5s(java),异步发送客服消息

- - CSDN博客综合推荐文章
在微信开发中我们会经常遇到在处理业务逻辑超过5s的情况,在超时时,微信会重新请求,总共请求三次,这样就会导致一系列的问题,怎样避免这些问题呢. 通过研究发现在微信官方文档清楚写着,如下:. 假如服务器无法保证在五秒内处理并回复,必须做出下述回复,这样微信服务器才不会对此作任何处理,并且不会发起重试(这种情况下,可以使用客服消息接口进行异步回复),否则,将出现严重的错误提示.

浅谈中文文本自动纠错在影视剧搜索中应用与Java实现

- - 博客园_首页
  这周由于项目需要对搜索框中输入的错误影片名进行校正处理,以提升搜索命中率和用户体验,研究了一下中文文本自动纠错(专业点讲是校对,proofread),并初步实现了该功能,特此记录.   中文输入错误的校对与更正是指在输入不常见或者错误文字时系统提示文字有误,最简单的例子就是在word里打字时会有红色下划线提示.

微信搜索引擎外站对接开放如何做微信首页排名SEO优化

- - 神刀安全网
是的,没错,微信也有 SEO. 百度是搜索引擎,所以有百度 SEO ;阿里巴巴有内部搜索引擎,所以有阿里 SEO ;淘宝有内部搜索引擎,所以有淘宝 SEO…… 凡是有搜索引擎存在的地方,就会有 SEO. 正如百度 SEO 刚刚出来的时候,利用百度 SEO 的很多中小企业都获得了成功. 现在,微信 SEO 也已出来,最近更是已经由封闭式内部搜索实现了微信公众号的 “ 外网 ” 全面权威展示.

Java中的锁(Locks in Java)

- - 并发编程网 - ifeve.com
原文链接 作者:Jakob Jenkov 译者:申章 校对:丁一. 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂. 因为锁(以及其它更高级的线程同步机制)是由synchronized同步块的方式实现的,所以我们还不能完全摆脱synchronized关键字( 译者注:这说的是Java 5之前的情况).

Java PaaS 对决

- 呆瓜 - IBM developerWorks 中国 : 文档库
本文为 Java 开发人员比较了三种主要的 Platform as a Service (PaaS) 产品:Google App Engine for Java、Amazon Elastic Beanstalk 和 CloudBees [email protected] 它分析了每种服务独特的技术方法、优点以及缺点,而且还讨论了常见的解决方法.