redis GEO数据结构、实现附近商铺功能实践
一、GEOGrolocation意为地理坐标允许存储地理坐标信息完成地理坐标之间距离的计算。geoadd key longitude1 latitude1 field1 longitude2 latitude2 field2...向图key中添加多个member包含经度longitude、纬度latitude 、member唯一标识fieldgeodist key field1 field2 [m,km]返回两个member之间的距离geohash key field1将指定member的坐标转为hash字符串形式并返回geopos key field1返回指定member的坐标geoseartch key FROMLONLAT longitude1 latitude1 [BYRADIUS 10km] [ASC/DESC] [WITHDIST]给定圆心和半径按照升序或降序返回指定范围内的member并返回距离具体值WITHDISTgeosearchstore同geoseratch并将结果存储到指定的key中GEO底层是用sortedSet实现其中经纬度会被换算为score字段(scoreab的意思)member唯一标识作为value字段。二、redis实现查询附近商铺功能1.按照商铺类型导入商铺信息1234567891011121314ResourceStringRedisTemplate stringRedisTemplate;ResourceIShopService shopService;TestpublicvoidtestLoadShopData(){ListShop shops shopService.query().list();for(Shop shop : shops) {stringRedisTemplate.opsForGeo().add(geo:shop:shop.getTypeId(),newRedisGeoCommands.GeoLocation(shop.getId().toString(),newPoint(shop.getX().doubleValue(),shop.getY().doubleValue())));}2.根据商铺类型和距离查询附近商铺1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950OverridepublicResult queryShopByType(Integer typeId, Integer current, Double x, Double y) {if(xnull|| ynull){// 根据类型分页查询PageShop page query().eq(type_id, typeId).page(newPage(current,5));// 返回数据returnResult.ok(page.getRecords());}// 该页起始和终止元素intfrom (current-1)*5;intend from 5;// 查询距离内的店铺GeoResultsRedisGeoCommands.GeoLocationString radius stringRedisTemplate.opsForGeo().radius(geo:shop: typeId,newCircle(newPoint(x, y),newDistance(5000)),RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance());//指定圆心半径m查相关店铺并返回店铺距离圆心的距离// 判空if(radiusnull){returnResult.ok(Collections.emptyList());}// 这里看类的结构只能getContentListGeoResultRedisGeoCommands.GeoLocationString results radius.getContent();// 判该页是否有元素if(results.size()from){returnResult.ok(Collections.emptyList());}// 截取from~end部分实现分页ListGeoResultRedisGeoCommands.GeoLocationString results1 results.subList(from, Math.min(end, results.size()-1));ArrayListLong shopIds newArrayList();HashMapLong, Distance longDistanceHashMap newHashMap();results1.forEach(r -{String shopId r.getContent().getName();shopIds.add(Long.valueOf(shopId));Distance distance r.getDistance();longDistanceHashMap.put(Long.valueOf(shopId), distance);});ListShop shops listByIds(shopIds);for(Shop s : shops) {doublevalue longDistanceHashMap.get(s.getId()).getValue();s.setDistance(value);}returnResult.ok(shops);}