前言

现在是移动互联网的时代,几乎人手一个手机,而手机可以很轻松的获取到用户的定位信息,也就是经纬度。而交友APP的基础就是经纬度,它的核心功能一个是寻找附近的人,一个是查看对方与你的直线距离,而这些功能,用redis的新数据类型GEO可以很方便的实现。

GEO

常用命令

存储地址空间位置

geoadd key longitude latitude member

返回两个位置间的距离

geodist key member1 member2 [m|km]

返回指定元素周边的元素

georadiusbymember key member radius m|km

案例

好了,命令讲完了,直接上代码,毕竟,talk is cheap, show me the code!  (*^▽^*)

public class GeoController extends BaseController {
    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping
    @ApiOperation(value = "手机上线,报告经纬度")
    public Result online(String name, double longitude, double latitude) {
        redisTemplate.opsForGeo().add("geo", new Point(longitude, latitude), name);
        return resultOk();
    }

    @GetMapping
    @ApiOperation(value = "获取成员经纬度")
    public Result<Point> online(String name) {
        List<Point> points = redisTemplate.opsForGeo().position("geo", name);
        if (CollectionUtil.isEmpty(points)) {
            return resultOk();
        }
        return resultOk(points.get(0));
    }

    @GetMapping(value = "/geodist")
    @ApiOperation(value = "获取成员间距离")
    public Result geodist(String member1, String member2) {
        //获取两个成员间距离,单位km
        Distance distance = this.redisTemplate.opsForGeo().distance("geo", member1, member2, RedisGeoCommands.DistanceUnit.KILOMETERS);
        return resultOk(distance);
    }

    @GetMapping(value = "/georadiusByMember")
    @ApiOperation(value = "获取成员附近的人")
    public Result<GeoResults> radiusByMember(String member) {
        //返回结果按距离升序,包含距离和经纬度, 返回50条
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(50);
        //半径10公里内
        Distance distance = new Distance(10, Metrics.KILOMETERS);
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = this.redisTemplate.opsForGeo().radius("geo", member, distance, args);
        return resultOk(geoResults);
    }

    @GetMapping(value = "/georadius")
    @ApiOperation(value = "获取指定经纬度附近的人")
    public Result<GeoResults> georadius(double longitude, double latitude) {
        //半径10公里内
        Distance distance = new Distance(10, Metrics.KILOMETERS);
        //根据经纬度生成范围
        Circle circle = new Circle(new Point(longitude, latitude), distance);
        //返回结果按距离升序,包含距离和经纬度, 返回50条
        RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending().limit(50);
        GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = this.redisTemplate.opsForGeo().radius("geo", circle, args);
        return resultOk(geoResults);
    }
}

演示

获取小张和小美间的距离,可以看到小张和小美之间只有200M

 查看小张附近的人,可以看到小张附近有小美和小爱

 参考项目(模块: SpringBoot-HelloWorld): https://gitee.com/huatin/java-test  

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐