当前位置: 代码网 > it编程>数据库>Redis > redis GEO数据结构、实现附近商铺功能实践

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

2025年12月24日 Redis 我要评论
一、geogrolocation意为地理坐标,允许存储地理坐标信息,完成地理坐标之间距离的计算。geoadd key longitude1 latitude1 field1 longitude2 la

一、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实现查询附近商铺功能

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 = stringredistemplate.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.emptylist());
    }

    // 截取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 : shops) {
        double value = longdistancehashmap.get(s.getid()).getvalue();
        s.setdistance(value);
    }

    return result.ok(shops);
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com