/**
* 商铺地理坐标导入redis
*/
@Test
public void loadShopData() {
List<Shop> shops = shopService.lambdaQuery().list();
Map<Long, List<Shop>> map = shops.stream().collect(Collectors.groupingBy(Shop::getTypeId));
for (Map.Entry<Long, List<Shop>> entry : map.entrySet()) {
Long typeId = entry.getKey();
String redisKey = "shop:geo:" + typeId;
List<Shop> value = entry.getValue();
List<RedisGeoCommands.GeoLocation<String>> geoLocations = new ArrayList<>(value.size());
for (Shop shop : value) {
geoLocations.add(new RedisGeoCommands.GeoLocation<String>(shop.getId().toString(), new Point(shop.getX(), shop.getY())));
}
stringRedisTemplate.opsForGeo().add(redisKey, geoLocations);
}
}
/**
* 根据商铺类型分页查询商铺信息
*
* @param current 页码
* @param typeId 商铺类型
* @param x 经度
* @param y 纬度
* @return
*/
@GetMapping("/of/type")
public Result queryShopByType(
@RequestParam(value = "current", defaultValue = "1") Integer current,
@RequestParam("typeId") Integer typeId,
@RequestParam(value = "x", required = false) Double x,
@RequestParam(value = "y", required = false) Double y) {
return shopService.queryShopByType(typeId, current, x, y);
}
@Override
public Result queryShopByType(Integer typeId, Integer current, Double x, Double y) {
//不需要根据坐标查询
if (x == null || y == null) {
Page<Shop> page = lambdaQuery().eq(Shop::getTypeId, typeId).page(new Page<>(current, SystemConstants.DEFAULT_PAGE_SIZE));
List<Shop> shops = page.getRecords();
return Result.ok(shops);
}
//计算分页参数
int from = (current - 1) * SystemConstants.DEFAULT_PAGE_SIZE;
int end = current * SystemConstants.DEFAULT_PAGE_SIZE;
//{redisKey,Location(shopId,x,y)}
String redisKey = RedisConstant.REDIS_SHOP_GEO_PREFIX + typeId;
GeoResults<RedisGeoCommands.GeoLocation<String>> results = stringRedisTemplate.opsForGeo().search(
redisKey,
GeoReference.fromCoordinate(x, y),
new Distance(3000),
RedisGeoCommands.GeoSearchCommandArgs.newGeoSearchArgs().includeDistance().limit(end));
if (results == null) {
return Result.ok(Collections.emptyList());
}
List<GeoResult<RedisGeoCommands.GeoLocation<String>>> geoResults = results.getContent();
//没有下一页
if (from >= geoResults.size()) {
return Result.ok(Collections.emptyList());
}
List<Long> shopIds = new ArrayList<>(geoResults.size());
Map<String, Distance> distanceMap = new HashMap<>();
//skip截取from-end 或者使用subList()
geoResults.stream().skip(from).forEach(result -> {
//redis.member 店铺id
String shopId = result.getContent().getName();
shopIds.add(Long.valueOf(shopId));
//店铺距离
Distance distance = result.getDistance();
distanceMap.put(shopId, distance);
});
//根据id查询商铺,保证有序,距离由近到远
String shopIdStr = StringUtils.joinWith(",", shopIds.toArray());
List<Shop> shops = lambdaQuery().in(Shop::getId, shopIds).last("ORDER BY FIELD(id," + shopIdStr + ")").list();
//填充非数据库字段
for (Shop shop : shops) {
Distance distance = distanceMap.get(shop.getId().toString());
shop.setDistance(distance.getValue());
}
return Result.ok(shops);
}