最近要做一个站点提醒的功能,找了很多资料,原来 redis里支持这种功能,简直是完美解决问题
先说原理 , GEOhash 原理就是把经纬度分别以二进制表示,再奇偶插入等到一个hash值,保存,相同的经纬度保存的地址相近,这样在取范围的时候,可以拿出相近的经纬度,
再就是边界问题, 因为是不断的划分区域,所以在边界查询的时候,会把上评级的四个区域都拿出来,所以本质也是个zset有序集合,
大家可以网上找些例子了解下,直接保存经纬代码
//提供地图坐标GeoHash保存站点,redis支持的类型存储
@Override
public boolean saveRedisGeo(JSONObject str) {
this.geoOperations = redisTemplate.opsForGeo();
this.zsetOperations = redisTemplate.opsForZSet();
List<Object> listsite = str.getJSONArray("lineLoad");
String carId = str.getString("carID").trim();
String geoKey="";
Map<String,Point> memberCoordinateMap = new HashMap<String, Point>();
Point geoCoordinate=null;
for(int i=0;i<listsite.size();i++){
JSONObject objsite = (JSONObject) listsite.get(i);
geoCoordinate = new Point(objsite.getDoubleValue("lng"), objsite.getDoubleValue("lat"));
geoKey = carId+"#"+objsite.getString("id")+"#"+objsite.getString("siteName")+"#"+objsite.getString("address")+"#"+str.getString("sendCarDate");
memberCoordinateMap.put(geoKey, geoCoordinate);
}
geoOperations.geoAdd("ELEF:SITE:"+carId, memberCoordinateMap);
zsetOperations.getOperations().expire("ELEF:SITE:"+carId,36L, TimeUnit.HOURS);
return true;
}
下面就是取出站点, 车子到哪里了, 然后传入经纬度,相应的距离计算得出
/* TMS系统地理坐标,附近站点,半径等 无需计算得到距离 */
private void getGeohashSite(String carid,JSONObject message){
GeoRadiusCommandArgs geoRadiusArgs = GeoRadiusCommandArgs.newGeoRadiusArgs();
geoRadiusArgs = geoRadiusArgs.includeCoordinates().includeDistance();//查询返回结果包括距离和坐标
if (Direction.ASC.equals(Direction.ASC)) {//按查询出的坐标距离中心坐标的距离进行排序
geoRadiusArgs.sortAscending();
} else if (Direction.DESC.equals(Direction.DESC)) {
geoRadiusArgs.sortDescending();
}
geoRadiusArgs.limit(2);//限制查询数量 distance 距离
GeoResults<GeoLocation<String>> radiusGeo = geoOperations.geoRadius("ELEF:SITE:"+carid, new Circle(new Point(Double.parseDouble(message.getString("longitude")), Double.parseDouble(message.getString("latitude"))), new Distance(3, DistanceUnit.KILOMETERS)), geoRadiusArgs);
Iterator<GeoResult<GeoLocation<String>>> result =radiusGeo.iterator();
while(result.hasNext()){
GeoResult<GeoLocation<String>> geoLocation = result.next();
// System.out.println(geoLocation.getDistance().getValue());
// System.out.println(geoLocation.getContent().getName());
String[] sts = geoLocation.getContent().getName().split("#");//拼接拆开
if(sts[0].equals(carid) && geoLocation.getDistance().getValue()<1.5){
// geoSendMessage(sts[0],sts[2],sts[3],sts[4]);
// zsetOperations.remove("ELEF:SITE:"+carid, geoLocation.getContent().getName());
break;
}
}
}
代码就这么多, 刚开始因为不懂这个功能,写了很多代码,还不如这几行代码简洁,