18 5 月, 2024

Manufacturing

Processing Machinery

Microservice SpringBoot integrates Redis GEO to realize the function of nearby merchants

3 min read

1. Usage of Redis GEO data structure

⛅GEO basic syntax and commands
GEO is the abbreviation of GeoLocation, which stands for geographic coordinates. Redis added support for GEO in version 3.2, which allows storing geographic coordinate information and helping us retrieve data based on latitude and longitude.

common commands

GEOADD: Add a geospatial information, including: longitude (longitude), latitude (latitude), value (member)
GEODIST: Calculate the distance between the specified two points and return
GEOHASH: Convert the coordinates of the specified member into a hash string and return
GEOPOS: returns the coordinates of the specified member
GEORADIUS: Specify the center and radius of the circle, find all the members contained in the circle, sort them according to the distance from the center of the circle, and return them. 6. Obsolete in the future
GEOSEARCH: Search for members within the specified range, and return them sorted by distance from the specified point. Ranges can be circular or rectangular. 6.2. New features
GEOSEARCHSTORE: The function is the same as GEOSEARCH, but the result can be stored in a specified key. 6.2. New features
⚡Use GEO to store latitude and longitude and query distance
The Redis version of this blog post is version 6.2

Enter redis to query geo related commands

在这里插入图片描述

Use GEO to complete the following functions Realize the distance query between two points, and the places within the specified range

The requirements are as follows

Add Beijing (Tiananmen 116.397469 39.908821, Forbidden City 116.397027 39.918056, Beihai Park 116.389977 39.933144) latitude and longitude using GEO
Check the distance between Tiananmen Square and the Forbidden City
Search places 2 kilometers near Tiananmen Square (116.397827 39.90374) in the places added above
GEOADDAdd
在这里插入图片描述

GEOPOS View the latitude and longitude information of the specified location

在这里插入图片描述

Expansion: The difference between GEOPOS and GEOHASH is that GEOHASH saves the memory of longitude and latitude storage, reduces unnecessary memory consumption, and thus improves performance

GEODIST checks the distance between Tiananmen Square and the Forbidden City在这里插入图片描述

GEOSEARCH finds places within 2km of Tiananmen Square

在这里插入图片描述

2. SpringBoot integrates Redis to import store data to GEO
Write SpringBoot unit tests to import Redis data

@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);
}

}

After running, just check Redis在这里插入图片描述

3. SpringBoot integrates Redis to realize the function of nearby merchants
☁️Requirements introduction
Based on the dark horse review project to realize the query function of nearby merchants

Use the GEO data structure to realize the query of nearby merchants
Complete the pagination function
Idea analysis:

Through the transmitted x, y latitude and longitude, we then query the nearby merchants in redis according to the longitude and latitude, and return it after finding out, package it, and add the found result to the distance of the Shop location in a loop, and it can be completed.

⚡Core source code
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);
}

carry out testing

在这里插入图片描述

Effect map of nearby merchants

在这里插入图片描述