⛄引言
本文参考黑马 点评我的项目
在点评我的项目中 如何 实现 左近商家的查问呢,展现出间隔本人5公里内的商户,这样的性能如何实现?
答案是能够采纳Redis 来实现,当然可能有很多实现形式,本文次要介绍如何应用Redis实现 左近商户的搜寻性能
一、Redis GEO 数据结构用法
⛅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.397469 39.908821 、故宫 116.397027 39.918056、北海公园 116.389977 39.933144) 经纬度
查问 天安门 与 故宫之间的间隔
在以上增加的地点中查问 天安门广场 (116.397827 39.90374) 左近2公里的地点
GEOADD 增加
GEOPOS 查看指定地点 经纬度信息
GEOHASH 查看指定地址 经纬度HASH值
拓展: GEOPOS 和 GEOHASH 的区别在于 GEOHASH 节约了 经纬度存储的 内存、缩小不必要的内存耗费,从而晋升性能
GEODIST 查看 天安门 与故宫之间的间隔
GEOSEARCH 查问 天安门广场 左近 2公里的地点
二、SpringBoot 整合Redis 导入 店铺数据 到GEO
编写SpringBoot 单元测试进行导入Redis数据
@Resource
private IShopService shopService;
@Resource
private StringRedisTemplate stringRedisTemplate;
@Test
void loadShopData() {
//1. 查问店铺信息
List<Shop> shopList = shopService.list();
//2. 把店铺分组,依照typeId分组、typeId统一的放在一个汇合
Map<Long, List<Shop>> map = shopList.stream().collect(Collectors.groupingBy(Shop::getTypeId));
//3. 分批实现写入redis
for (Map.Entry<Long, List<Shop>> entry : map.entrySet()) {
//3.1 获取类型id
Long typeId = entry.getKey();
String key = RedisConstants.SHOP_GEO_KEY + typeId;
//3.2 获取同类型的店铺的汇合
List<Shop> value = entry.getValue();
List<RedisGeoCommands.GeoLocation<String>> locations = new ArrayList<>(value.size());
//3.3 写入redis GEOADD key 经度 维度 member
for (Shop shop : value) {
locations.add(new RedisGeoCommands.GeoLocation<>(
shop.getId().toString(),
new Point(shop.getX(), shop.getY())));
}
stringRedisTemplate.opsForGeo().add(key, locations);
}
}
复制代码
运行结束,查看Redis即可
三、SpringBoot 整合 Redis 实现 左近商户性能
☁️需要介绍
基于黑马点评我的项目实现 左近商户查问性能
采纳GEO 数据结构实现左近商户查问
实现分页性能
思路剖析:
通过传输过去的 x、y 经纬度,而后咱们依据该经纬度去查问redis中左近的商户,查出后即可返回,进行封装,查出来的后果进行循环增加至 Shop 地点间隔,即可实现。
⚡外围源码
ShopController
@GetMapping(“/of/type”)
public Result queryShopByType(
@RequestParam("typeId") Integer typeId,
@RequestParam(value = "current", defaultValue = "1") Integer current,
@RequestParam(value = "x", required = false) Double x,
@RequestParam(value = "y", required = false) Double y) {
return shopService.queryShopByType(typeId, current, x, y);
}
复制代码
ShopService
@Override
public Result queryShopByType(Integer typeId, Integer current, Double x, Double y) {
//1. 判断是否须要坐标查问
if (x == null || y == null) {
// 不须要坐标查问,按数据库查问
Page<Shop> page = query()
.eq("type_id", typeId)
.page(new Page<>(current, SystemConstants.DEFAULT_PAGE_SIZE));
// 返回数据
return Result.ok(page.getRecords());
}
//2. 计算分页参数
int form = (current - 1) * SystemConstants.DEFAULT_PAGE_SIZE;
int end = current * SystemConstants.DEFAULT_PAGE_SIZE;
//3. 查问redis,依照间隔排序、分页 后果:shopId、distance
String key = RedisConstants.SHOP_GEO_KEY + typeId;
GeoResults<RedisGeoCommands.GeoLocation<String>> results = stringRedisTemplate.opsForGeo().search(
key,
GeoReference.fromCoordinate(x, y),
new Distance(5000),
RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance().limit(end));
//4. 解析id
if (results == null) {
return Result.ok(Collections.emptyList());
}
List<GeoResult<RedisGeoCommands.GeoLocation<String>>> content = results.getContent();
//4.1 截取from => end
List<Long> ids = new ArrayList<>(content.size());
Map<String, Distance> distanceMap = new HashMap<>(content.size());
if (content.size() <= form) {
return Result.ok(Collections.emptyList());
}
content.stream().skip(form).forEach(result -> {
//4.2 获取店铺id
String shopIdStr = result.getContent().getName();
ids.add(Long.valueOf(shopIdStr));
//4.2 获取间隔
Distance distance = result.getDistance();
distanceMap.put(shopIdStr, distance);
});
//5. 依据id查问shop
String idStr = StrUtil.join(",", ids);
List<Shop> shops = query().in("id", ids).last("ORDER BY FIELD(id," + idStr + ")").list();
// 循环将 商品间隔放入对象间隔属性中
shops.forEach(shop -> {
shop.setDistance(distanceMap.get(shop.getId().toString()).getValue());
});
//6. 返回后果
return Result.ok(shops);
}
复制代码
进行测试
✅左近商户效果图
⛵小结
以上就是【Bug 终结者】对 微服务 SpringBoot 整合 Redis 实现左近商户性能 的简略介绍,左近商户搜寻,是很常见的性能,把握GEO即可实现该相似的需要,并高质量实现开发,加油! 认真练习,晋升技术。 技术扭转世界!!!
发表回复