在点评项目中如何实现附近商家的查询呢,展示出距离自己5公里内的商户,这样的功能如何实现? 答案是可以采用Redis来实现,当然可能有很多实现方式,本文主要介绍如何使用Redis实现附近商户的搜索功能一、RedisGEO数据结构用法 GEO基本语法、指令 GEO就是GeoLocation的简写形式,代表地理坐标。Redis在3。2版本中加入了对GEO的支持,允许存储地理坐标信息,帮助我们根据经纬度来检索数据。 常见的命令GEOADD:添加一个地理空间信息,包含:经度(longitude)、纬度(latitude)、值(member)GEODIST:计算指定的两个点之间的距离并返回GEOHASH:将指定member的坐标转为hash字符串形式并返回GEOPOS:返回指定member的坐标GEORADIUS:指定圆心、半径,找到该圆内包含的所有member,并按照与圆心之间的距离排序后返回。6。以后已废弃GEOSEARCH:在指定范围内搜索member,并按照与指定点之间的距离排序后返回。范围可以是圆形或矩形。6。2。新功能GEOSEARCHSTORE:与GEOSEARCH功能一致,不过可以把结果存储到一个指定的key。6。2。新功能使用GEO存储经纬度、查询距离 本篇博文Redis版本为6。2版本 进入redis查询geo相关指令 使用GEO完成以下功能实现两点之间的距离查询,以及指定范围内的地点 需求如下:使用GEO添加北京(天安门116。39746939。908821、故宫116。39702739。918056、北海公园116。38997739。933144)经纬度查询天安门与故宫之间的距离在以上添加的地点中查询天安门广场(116。39782739。90374)附近2公里的地点 GEOADD添加 GEOPOS查看指定地点经纬度信息 GEOHASH查看指定地址经纬度HASH值 拓展:GEOPOS和GEOHASH的区别在于GEOHASH节约了经纬度存储的内存、减少不必要的内存消耗,从而提升性能 GEODIST查看天安门与故宫之间的距离 GEOSEARCH查询天安门广场附近2公里的地点 二、SpringBoot整合Redis导入店铺数据到GEO 编写SpringBoot单元测试进行导入Redis数据ResourceprivateIShopServiceshopService;ResourceprivateStringRedisTemplatestringRedisTemplate;TestvoidloadShopData(){1。查询店铺信息ListShopshopListshopService。list();2。把店铺分组,按照typeId分组、typeId一致的放在一个集合MapLong,ListShopmapshopList。stream()。collect(Collectors。groupingBy(Shop::getTypeId));3。分批完成写入redisfor(Map。EntryLong,ListShopentry:map。entrySet()){3。1获取类型idLongtypeIdentry。getKey();StringkeyRedisConstants。SHOPGEOKEYtypeId;3。2获取同类型的店铺的集合ListShopvalueentry。getValue();ListRedisGeoCommands。GeoLocationStringlocationsnewArrayList(value。size());3。3写入redisGEOADDkey经度维度memberfor(Shopshop:value){locations。add(newRedisGeoCommands。GeoLocation(shop。getId()。toString(),newPoint(shop。getX(),shop。getY())));}stringRedisTemplate。opsForGeo()。add(key,locations);}} 运行完毕,查看Redis即可 三、SpringBoot整合Redis实现附近商户功能 需求介绍 实现附近商户查询功能采用GEO数据结构实现附近商户查询完成分页功能 思路分析: 通过传输过来的x、y经纬度,然后我们根据该经纬度去查询redis中附近的商户,查出后即可返回,进行封装,查出来的结果进行循环添加至Shop地点距离,即可完成。核心源码 ShopControllerGetMapping(oftype)publicResultqueryShopByType(RequestParam(typeId)IntegertypeId,RequestParam(valuecurrent,defaultValue1)Integercurrent,RequestParam(valuex,requiredfalse)Doublex,RequestParam(valuey,requiredfalse)Doubley){returnshopService。queryShopByType(typeId,current,x,y);} ShopServiceOverridepublicResultqueryShopByType(IntegertypeId,Integercurrent,Doublex,Doubley){1。判断是否需要坐标查询if(xnullynull){不需要坐标查询,按数据库查询PageShoppagequery()。eq(typeid,typeId)。page(newPage(current,SystemConstants。DEFAULTPAGESIZE));返回数据returnResult。ok(page。getRecords());}2。计算分页参数intform(current1)SystemConstants。DEFAULTPAGESIZE;intendcurrentSystemConstants。DEFAULTPAGESIZE;3。查询redis,按照距离排序、分页结果:shopId、distanceStringkeyRedisConstants。SHOPGEOKEYtypeId;GeoResultsRedisGeoCommands。GeoLocationStringresultsstringRedisTemplate。opsForGeo()。search(key,GeoReference。fromCoordinate(x,y),newDistance(5000),RedisGeoCommands。GeoSearchCommandArgs。newGeoSearchArgs()。includeDistance()。limit(end));4。解析idif(resultsnull){returnResult。ok(Collections。emptyList());}ListGeoResultRedisGeoCommands。GeoLocationStringcontentresults。getContent();4。1截取fromendListLongidsnewArrayList(content。size());MapString,DistancedistanceMapnewHashMap(content。size());if(content。size()form){returnResult。ok(Collections。emptyList());}content。stream()。skip(form)。forEach(result{4。2获取店铺idStringshopIdStrresult。getContent()。getName();ids。add(Long。valueOf(shopIdStr));4。2获取距离Distancedistanceresult。getDistance();distanceMap。put(shopIdStr,distance);});5。根据id查询shopStringidStrStrUtil。join(,,ids);ListShopshopsquery()。in(id,ids)。last(ORDERBYFIELD(id,idStr))。list();循环将商品距离放入对象距离属性中shops。forEach(shop{shop。setDistance(distanceMap。get(shop。getId()。toString())。getValue());});6。返回结果returnResult。ok(shops);} 进行测试 作者:Bug终结者 链接:https:juejin。cnpost7187937697883750457