Redis实现简单附近人功能

Redis实现简单附近人功能

1、用户进入附近人页面传经纬度地址存入表中。
2、根据经纬度地址计算出该用户距离范围内用户。
3、使用 Redis 根据行政编码分类存放 用户。
4、具体逻辑根据业务需求完善 ...... 博主结合了各种筛选条件在线离线状况这里不一一列举。
  • 数据库表
    在这里插入图片描述
  • Redis 存放结构(使用hash存储方便用户更新坐标操作)城市key在这里插入图片描述
  • controller接口
    在这里插入图片描述
  • 附近人入参DTO类
/**
 * @author Created by John on 2019/11/23
 */
@Data
public class NearbyDTO extends BaseDto {
    @ApiModelProperty(value = "城市编码", name = "cityCode")
    @NotNull(message = "城市编码不能为空")
    private Integer cityCode;
    @ApiModelProperty(value = "省份编码", name = "adCode")
    @NotNull(message = "省份编码不能为空")
    private Integer adCode;
    @NotNull(message = "经度不能为空")
    private Double lng;
    @NotNull(message = "纬度不能为空")
    private Double lat;
    @NotNull(message = "标签不能为空")
    private String label;
    @ApiModelProperty(value = "距离:KM", name = "scope")
    private int scope;
}
  • Service 业务代码
@Override
    public List<NearbyVO> nearbyList(NearbyDTO dto) {

        SysUser user = sysUserService.selectById(userToken.getUserId());
        // 缓存key值
        String cacheKey = String.format(NEARBY_CACHE_KEY, dto.getCityCode(), dto.getAdCode());

        NearbyVO vo = new NearbyVO();
        vo.setUid(user.getId());
        vo.setLng(dto.getLng());
        vo.setLat(dto.getLat());
        vo.setLabel(dto.getLabel());
        BeanUtils.copyProperties(user, vo);

        // 使用hash更加快速的定位到用户缓存信息,便于删除更新
        redisDao.hset(cacheKey, user.getId() + "", JSONObject.toJSONString(vo));

        // 从当前地区缓存中获取全部用户(包括用户自己)
        Map<String, String> cacheAll = redisDao.hGetAll(cacheKey);

        if (cacheAll.isEmpty() || cacheAll.size() == 0) return null;

        if (dto.getScope() > MAX_DISTANCE) {
            dto.setScope(MAX_DISTANCE);
        }

        // 结果集,-1是要排除用户自己
        List<NearbyVO> result = new ArrayList<NearbyVO>();

        for (String item : cacheAll.keySet()) {
            NearbyVO bo = JSONObject.parseObject(cacheAll.get(item), NearbyVO.class);
            double distance = MapUtils.getDistance(dto.getLat(), dto.getLng(), bo.getLat(), bo.getLng());
            // 排除距离以外的用户
            if (distance > dto.getScope()) {
                continue;
            }

            bo.setScope(distance);
            result.add(bo);
        }
        // 根据距离排序 由近 -> 到远
        if (!result.isEmpty()) {
            Collections.sort(result, new Comparator<NearbyVO>() {
                @Override
                public int compare(NearbyVO o1, NearbyVO o2) {
                    if (o1.getScope() > o2.getScope()) {
                        return 1;
                    }
                    if (o1.getScope() == o2.getScope()) {
                        return 0;
                    }
                    return -1;
                }
            });
        }
        // 后期分页
        //Page page = new Page(dto.getPage(), dto.getRows());

        // 开启一个新线程 同步数据库信息
        threadPoolTaskExecutor.execute(new Runnable() {
            @Override
            @Transactional(rollbackFor = Exception.class)
            public void run() {
                NearbyUser nearbyUser = new NearbyUser();
                nearbyUser.setUid(user.getId());
                nearbyUser.setLable(dto.getLabel());
                nearbyUser.setLat(dto.getLat());
                nearbyUser.setLng(dto.getLng());
                nearbyUser.setCreateTime(new Date());

                Wrapper<NearbyUser> wrapper = new EntityWrapper<NearbyUser>().eq("uid", user.getId());
                Integer flag = 0;
                if (nearbyUserMapper.selectCount(wrapper) > 0) {
                    flag = nearbyUserMapper.update(nearbyUser, wrapper);
                } else {
                    flag = nearbyUserMapper.insert(nearbyUser);
                }
                log.info("------> 用户【{}】同步数据到附近用户表状态为【{}】、注.0 失败 >1 成功", user.getId(), flag);
            }
        });
        return result;
    }
  • 效果图
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43254936/article/details/105594723