共计 3934 个字符,预计需要花费 10 分钟才能阅读完成。
⛄引言
本文参考黑马 点评我的项目
在点评我的项目中 如何 实现 左近商家的查问呢,展现出间隔本人 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 即可实现该相似的需要,并高质量实现开发,加油!认真练习,晋升技术。技术扭转世界!!!