18.app后端如何实现LBS
移动互联网,除了一直在线这个特点外,还有一个重要特点,能定位到手机的位置。查找附近的人,附近的餐馆等服务,以及大量的o2o应用, 都需要使用LBS(Location Based Services)。那么,如何用户的地理坐标?如何去查找所需的附近的数据呢?在这篇文章中,为你一一道来。
现在,基于手机来获取用户的地理坐标,主要是下面两种方法:
(1)使用手机上的GPS模块
一般是使用第一种方法,当手机上没有GPS模块,就用第二种方法来定位。
app端建议直接使用地图sdk提供的获取地理坐标的方法来获取地理坐标,它会自动判断使用哪种方式的。
对于初次做LBS的小伙伴,地理坐标的偏移问题需要注意。通过手机获取的坐标,放到百度地图或高德地图上,总是会出现偏移,例如,当时是在微信的前总部“南方通讯大厦”附近获取的坐标,那是把坐标放到百度地图上却到了华南师范大学(那是俺的母校)。
被这个问题困扰了好久,查了好多资料才找到是这个原因:国家的法律规定,所有的电子地图服务提供商都需要给地图数据加上偏移和加密,例如,你获取的坐标是100,90 ,这个坐标到了地图上却变成了105,95,这个数据的差异就是偏移。
而且,这个偏移量没有明确规定,这就造成了一个现象,不同电子地图服务提供商有不同的坐标体系,例如,Google地图,高德地图,苹果地图是同一套坐标体系,百度地图却是另外一套坐标体系。
那么,怎么解决这个问题?方法很简单,使用地图sdk提供的获取地理坐标功能,获取的这个坐标是已经偏移过的。
一般的业务逻辑是,数据中有很多坐标,知道一个坐标,把一定范围内(例如500米内)的其他坐标查出来。
下面介绍3种实现方案:
参考资料:http://blog.csdn.net/chaiqi/article/details/23099407
从MySQL4.1开始,mysql就引入了一系列空间扩展,使其具备了一定的空间处理能力。
geohash的详细介绍,可参考 http://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html
geohash编码,可以把地理坐标转换成一个值,简单点来说就是把二维坐标转换成一维坐标。geohash表示的并不是一个点,而是一个矩形区域。比如编码w23yr3,它表示的是一个矩形区域。geohash编码的前缀可以表示更大的区域。例如w23yr3,它的前缀w23yr表示包含编码w23yr在内的更大范围。 这个特性可以用于附近地点搜索。
查找附近的时候,非常方便,用SQL中,LIKE ‘w23yr3%’可查询附近的所有地点。
在以前的产品中,一个需求是查找用户附近的商铺(包含关键字),商铺的数据有130万,全放在mysql中, 发现用mysql LIKE ‘w23yr3%’这种方式检索geohash性能上的瓶颈很大,检索130万行的数据,平均花费了8秒,这是响应速度是无法忍受的。
后来经过不断优化,确定了如下使用coreseek+redis+mysql解决方案,一下子就把响应速度减少到平均1 秒,这个方案的如下:
1. 用每个商铺的坐标值计算geohash,把geohash作为key,商铺的id作为value,放到redis的set集中。
2. 根据用户的坐标计算geohash,在redis中用"keys *"的方法匹配查找附近的商铺geohash(记得geohash的特点吗?geohash编码的前缀可以表示一个区域),再获得商铺的id
3. 把2中商铺的id作为filter ,在coreseek中继续查找。
地理位置支持是MongoDB的一大亮点,全球最流行的LBS服务foursquare,国内的快的,选择的也是mongodb。
使用mongodb开发LBS服务有以下的优点:
1. mongodb自身的性能高,更新,查询的速度快。
2. 通过副本集,分片等方法,很容易实现mongodb的分布式部署,解决性能瓶颈。
3. mongodb已在app后端中广泛使用,开发部署对于很多开发者来说都是比较熟悉。
用mongodb,可支持:
1. 查询多边形范围的坐标。
2. 查询附近的坐标。
3. 查询圆形区域内的坐标。
【QQ】190678908
【app后端qq群】254659220
【微信公众号】 appbackend
【新浪微博】 @newjueqi
【博客】http://blog.csdn.net/newjueqi
1.如何获取用户的地理坐标
现在,基于手机来获取用户的地理坐标,主要是下面两种方法:
(1)使用手机上的GPS模块
(2)使用手机网络所连接的基站定位
一般是使用第一种方法,当手机上没有GPS模块,就用第二种方法来定位。
app端建议直接使用地图sdk提供的获取地理坐标的方法来获取地理坐标,它会自动判断使用哪种方式的。
对于初次做LBS的小伙伴,地理坐标的偏移问题需要注意。通过手机获取的坐标,放到百度地图或高德地图上,总是会出现偏移,例如,当时是在微信的前总部“南方通讯大厦”附近获取的坐标,那是把坐标放到百度地图上却到了华南师范大学(那是俺的母校)。
被这个问题困扰了好久,查了好多资料才找到是这个原因:国家的法律规定,所有的电子地图服务提供商都需要给地图数据加上偏移和加密,例如,你获取的坐标是100,90 ,这个坐标到了地图上却变成了105,95,这个数据的差异就是偏移。
而且,这个偏移量没有明确规定,这就造成了一个现象,不同电子地图服务提供商有不同的坐标体系,例如,Google地图,高德地图,苹果地图是同一套坐标体系,百度地图却是另外一套坐标体系。
那么,怎么解决这个问题?方法很简单,使用地图sdk提供的获取地理坐标功能,获取的这个坐标是已经偏移过的。
2.如何查找附近的用户(商户,人)
一般的业务逻辑是,数据中有很多坐标,知道一个坐标,把一定范围内(例如500米内)的其他坐标查出来。
下面介绍3种实现方案:
(1) mysql的空间数据库
参考资料:http://blog.csdn.net/chaiqi/article/details/23099407
从MySQL4.1开始,mysql就引入了一系列空间扩展,使其具备了一定的空间处理能力。
简单点来说,就是mysql里已经可以把地理坐标的数据当成一种独立的数据类型,而且提供了相关的空间函数(例如查找一个矩形范围内的坐标)给开发者直接调用。
(2)geohash
geohash的详细介绍,可参考 http://www.cnblogs.com/dengxinglin/archive/2012/12/14/2817761.html
geohash编码,可以把地理坐标转换成一个值,简单点来说就是把二维坐标转换成一维坐标。geohash表示的并不是一个点,而是一个矩形区域。比如编码w23yr3,它表示的是一个矩形区域。geohash编码的前缀可以表示更大的区域。例如w23yr3,它的前缀w23yr表示包含编码w23yr在内的更大范围。 这个特性可以用于附近地点搜索。
查找附近的时候,非常方便,用SQL中,LIKE ‘w23yr3%’可查询附近的所有地点。
在以前的产品中,一个需求是查找用户附近的商铺(包含关键字),商铺的数据有130万,全放在mysql中, 发现用mysql LIKE ‘w23yr3%’这种方式检索geohash性能上的瓶颈很大,检索130万行的数据,平均花费了8秒,这是响应速度是无法忍受的。
后来经过不断优化,确定了如下使用coreseek+redis+mysql解决方案,一下子就把响应速度减少到平均1 秒,这个方案的如下:
1. 用每个商铺的坐标值计算geohash,把geohash作为key,商铺的id作为value,放到redis的set集中。
2. 根据用户的坐标计算geohash,在redis中用"keys *"的方法匹配查找附近的商铺geohash(记得geohash的特点吗?geohash编码的前缀可以表示一个区域),再获得商铺的id
3. 把2中商铺的id作为filter ,在coreseek中继续查找。
(3) mongodb
地理位置支持是MongoDB的一大亮点,全球最流行的LBS服务foursquare,国内的快的,选择的也是mongodb。
使用mongodb开发LBS服务有以下的优点:
1. mongodb自身的性能高,更新,查询的速度快。
2. 通过副本集,分片等方法,很容易实现mongodb的分布式部署,解决性能瓶颈。
3. mongodb已在app后端中广泛使用,开发部署对于很多开发者来说都是比较熟悉。
用mongodb,可支持:
1. 查询多边形范围的坐标。
2. 查询附近的坐标。
3. 查询圆形区域内的坐标。
强烈推荐LBS服务中优先使用mongodb!!!
---------------------------------------------------------------------------------------------------------------------------
打开链接 app后端系列文章总目录 总目录 ,能查看本人发表过的所有原创“app后端”文章。
【作者】曾健生
【QQ】190678908
【app后端qq群】254659220
【微信公众号】 appbackend
【新浪微博】 @newjueqi
【博客】http://blog.csdn.net/newjueqi
版权声明:本文为博主原创文章,未经博主允许不得转载。