目录
一、大数据统计之GEO
1.1、面试题
1.2、获得地址的经纬度
1.3、GEO相关指令
1.4、需求分析
1.5、架构设计
1.6、代码实现
一、大数据统计之GEO
1.1、面试题
移动互联网时代LBS应用越来越多,交友软件中附近的妹子,外卖软件中附近的美食店铺,打车软件中附近的车辆,这些软件中是如何实现的?
出现的问题:
1、查询性能问题,当在并发高,数据量访问大的情况下查询会搞垮MySQL数据库。
2、一般MySQL查询的是一个平面矩形访问,而叫车服务要以自己为中心N公里半径的圆形覆盖。
3、矩形计算在长距离计算时会有很大误差,MySQL不合适。
1.2、获得地址的经纬度
经纬度查询定位 拾取坐标系统 经纬度查询地图
1.3、GEO相关指令
GEOADD添加经纬度坐标
注意:
有中文乱码需要在进时redis-cli -a xxxxxx -raw
GEOPOS返回经纬度
GEOHASH返回坐标的geohash表示
GEODIST两个位置之间的距离
GEORADIUS
GEORADIUSBYMEMBER
1.4、需求分析
某app上搜索附近的酒店距离自己多远
相亲app上小姐姐的距离
某地图软件上附近的人,景区、酒店等
1.5、架构设计
redis的GEO类型实现
1.6、代码实现
@Service
@Slf4j
public class GEOService {public static final String CITY = "city";@Autowiredprivate RedisTemplate redisTemplate;public String geoAdd() {HashMap<String,Point> map = new HashMap<>();//将地标名与经纬度存入map中map.put("交子公园",new Point(104.08044 , 30.59152 ));map.put("金融麦田",new Point(104.07260 , 30.58909 ));map.put("华商金融中心",new Point(104.07146 , 30.58722 ));//存入redisredisTemplate.opsForGeo().add(CITY,map);return map.toString();}public Point position(String member) {//获取经纬度坐标List<Point> list = redisTemplate.opsForGeo().position(CITY, member);//返回查询的值即第一个return list.get(0);}public String hash(String member) {//geohash算法生成的base32编码值List<String> list = redisTemplate.opsForGeo().hash(CITY, member);return list.get(0);}public Distance distance(String member1, String member2) {//获取两个给定位置之间的距离Distance distance = redisTemplate.opsForGeo().distance(CITY, member1, member2,RedisGeoCommands.DistanceUnit.KILOMETERS);return distance;}public GeoResults radiusByxy() {//通过经度纬度查找xxx附近Circle circle = new Circle(104.07260, 30.58909, Metrics.KILOMETERS.getMultiplier());//返回多少条记录RedisGeoCommands.GeoRadiusCommandArgs limit = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortDescending().limit(50);GeoResults<RedisGeoCommands.GeoLocation<String>> radius = redisTemplate.opsForGeo().radius(CITY, circle, limit);return radius;}public GeoResults radiusByMember() {//通过地名查找Distance distance = new Distance(50, Metrics.KILOMETERS);//返回多少条记录RedisGeoCommands.GeoRadiusCommandArgs limit = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortDescending().limit(50);GeoResults<RedisGeoCommands.GeoLocation<String>> radius = redisTemplate.opsForGeo().radius(CITY,"交子公园",distance,limit);return radius;}
}
@RestController
@Slf4j
@Api(tags = "酒店推送")
public class GEOController {@Autowiredprivate GEOService geoService;@ApiOperation("添加坐标geoAdd")@RequestMapping(value = "/geoAdd",method = RequestMethod.GET)public String geoAdd(){return geoService.geoAdd();}@ApiOperation("获取经纬度坐标position")@RequestMapping(value = "/position",method = RequestMethod.GET)public Point position(String member){return geoService.position(member);}@ApiOperation("获取经纬度生成的base32编码值hash")@RequestMapping(value = "/hash",method = RequestMethod.GET)public String hash(String member){return geoService.hash(member);}@ApiOperation("获取两个给定位置间的距离")@RequestMapping(value = "/distance",method = RequestMethod.GET)public Distance distance(String member1,String member2){return geoService.distance(member1,member2);}@ApiOperation("通过经度纬度查找xxx附近")@RequestMapping(value = "/radiusByxy",method = RequestMethod.GET)public GeoResults radiusByxy(){return geoService.radiusByxy();}@ApiOperation("通过地方查找附近")@RequestMapping(value = "/radiusByMember",method = RequestMethod.GET)public GeoResults radiusByMember(){return geoService.radiusByMember();}
}