开发者

redis GEO数据结构、实现附近商铺功能实践

开发者 https://www.devze.com 2025-12-25 08:58 出处:网络 作者: 姓蔡小朋友
价值2999元 Java视频教程限时免费下载
专为Java开发者设计,涵盖核心技术、架构设计、性能优化等
立即下载
目录一、GEO二、Redis实现查询附近商铺功能1.按照商铺类型导入商铺信息2.根据商铺类型和距离查询附近商铺总结一、GEO
目录
  • 一、GEO
  • 二、Redis实现查询附近商铺功能
    • 1.按照商铺类型导入商铺信息
    • 2.根据商铺类型和距离查询附近商铺
  • 总结

    一、GEO

    Grolocation意为地理坐标,允许存储地理坐标信息,完成地理坐标之间距离的计算。

    • geoadd key longitude1 latitude1 field1 longitude2 latitude2 field2...:向图key中添加多个member,包含经度longitude、纬度latitude 、member唯一标识field
    • geodist key field1 field2 [m,km]:返回两个member之间的距离
    • geohash key field1:将指定member的坐标转为hash字符串形式并返回
    • geopos key field1:返回指定member的坐标
    • geoseartch key FROMLONLAT longitude1 latitude1 [BYRADIUS 10km] [ASC/DESC] [WITHDIST]:给定圆心和半径,按照升序或降序返回指定范围内的member,编程客栈并返回距离具体值WITHDIST
    • geosearchstore:同geoseratch,并将结果存储到指定的key中

    GEO底层是用sortedSet实现,其中经纬度会被换算为score字段(score=a+b的意思),member唯一标识作为value字段。

    redis GEO数据结构、实现附近商铺功能实践

    二、redis实现查询附近商铺功能

    1.按照商铺类型导入商铺信息

    @Resource
    StringRedisTemplate stringRedisTemplate;
    @Resource
    IShopService shopService;
    @Test
    public void testLoadShopData(){
        List<Shop> shops = shopService.query().list();
        for (Shop shop : shops) {
            stringRedisTemplate.opsForGeo().add(
                    "geo:shop:"+shop.getTypeId(),
       编程客栈             new RedisGeoCommands.GeoLocation<>(
                            shop.getId().toString(),
                            new Point(shop.getX().doubleValue(),shop.getY().doubleValue())));
        }
    

    2.根据商铺类型和距离查询附近商铺

    @Override
    public Result queryShopByType(Integer typeId, Integer current, Double x, Double y) {
        if (x==null || y==null){
            // 根据类型分页查询
            Page<Shop> page = query()
                    .eq("type_id", typeId)
                    .page(new Page<>(current, 5));
            // 返回数据
            return Result.ok(page.getRecords());
        }
        // 该页起始和终止元素
        int from = (current-1)*5;
        int end = from + 5;
        // 查询距离内的店铺
        GeoResults<RedisGeoCommands.GeoLocation<String>> radius = stringRedisTe编程客栈mplate.opsForGeo().radius(
                "geo:shop:" + typeId,
                new Circle(new Point(x, y), new Distance(5000)),
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance());//指定圆心半径m查相关店铺,并返回店铺距离圆心的距离
        // 判空
        if (radius==null){
            return Result.ok(Collections.emptyList());
        }
        // 这里看类的结构只能getContent
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> results = radius.getContent();
    
        // 判该页是否有元素
        if (results.size()<=from){
            return Result.ok(Collections.empt编程客栈yList());
        }
    
        // 截取from~end部分实现分页
        List<GeoResult<RedisGeoCommands.GeoLocation<String>>> results1 = results.subList(from, Math.min(end, results.size()-1));
    
        ArrayList<Long> shopIds = new ArrayList<>();
        HashMap<Long, Distance> longDistanceHashMap = new HashMap<>();
        results1.forEach(r ->{
            String shopId = r.getContent().getName();
            shopIds.add(Long.valueOf(shopId));
            Distance distance = r.getDistance();
            longDistanceHashMap.put(Long.valueOf(shopId), distance);
        });
    
        List<Shop> shops = listByIds(shopIds);
        for (Shop s : shojavascriptps) {
            double value = longDistanceHashMap.get(s.getId()).getValue();
            s.setDistance(value);
        }
    
        return Result.ok(shops);
    }
    

    总结

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程客栈(www.devze.com)。

    0
    价值2999元 Java视频教程限时免费下载
    专为Java开发者设计,涵盖核心技术、架构设计、性能优化等
    立即下载

    精彩评论

    暂无评论...
    验证码 换一张
    取 消