SpringBoot教程 —— Java基于MySQL实现附近的人

准备工作

创建测试数据库

CREATE TABLE `userposition` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `city` varchar(20) NOT NULL,
    `position` varchar(128) NOT NULL,
    `longitude` decimal(18,15) NOT NULL,
    `latitude` decimal(18,15) NOT NULL,
    PRIMARY KEY (`id`)
)ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
insert into `userposition` values(1,'北京市','回龙观新村中区', 116.310771,40.06263);
insert into `userposition` values(2,'北京市','金域华府', 116.310127,40.064379);
insert into `userposition` values(3,'北京市','融泽嘉园中区', 116.311962,40.064822);
insert into `userposition` values(4,'北京市','回龙观新村东区', 116.312541,40.063246);
insert into `userposition` values(5,'北京市','上地东里', 116.314168,40.033075);

测试数据中的经度和纬度可以用高德地图或者百度地图提取。

附近的人

原理

先算出某个坐标位置周围的矩形的四个点,然后使用经纬度去直接匹配数据库中的记录。

思路

首先算出“给定坐标附近1000米”这个范围的坐标范围。 虽然它是个圆,但我们可以先求出该圆的外接正方形,然后拿正方形的经纬度范围去搜索数据库。圆形内为要求的搜索范围,方形内为我们能间接得到的结果范围。

先来求东西两侧的的范围边界。在haversin公式中令φ1 = φ2,可得

SpringBoot入门教程(五)Java基于MySQL实现附近的人

Java实现

/**
     * 查找附近的人
     * @param radii 半径距离(单位km)
     * @param lon 经度
     * @param lat 纬度
     * @return
     */
    @GetMapping("/nearby")
    public List<UserPosition> getVicinity(double radii, double lon, double lat){
        double r = 6371;//地球半径千米
        double dis = radii;
        double dlng =  2*Math.asin(Math.sin(dis/(2*r))/Math.cos(lat*Math.PI/180));
        dlng = dlng*180/Math.PI;//角度转为弧度
        double dlat = dis/r;
        dlat = dlat*180/Math.PI;
        double minlat =lat-dlat;
        double maxlat = lat+dlat;
        double minlng = lon -dlng;
        double maxlng = lon + dlng;

        return userService.getVicinity(BigDecimal.valueOf(minlng), BigDecimal.valueOf(maxlng), BigDecimal.valueOf(minlat), BigDecimal.valueOf(maxlat));
    }

mybatis

<select id="getvicinity" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from userposition
    where longitude >= #{minlng} and longitude <= #{maxlng} and latitude >= #{minlat} and latitude <= #{maxlat}
</select>
List<UserPosition> getvicinity(@Param("minlng") BigDecimal minlng,
                                  @Param("maxlng") BigDecimal maxlng,
                                  @Param("minlat") BigDecimal minlat,
                                  @Param("maxlat") BigDecimal maxlat);

测试效果

在地图中找到回龙新村的经纬度,然后测试。

 

按距离远近排序

Java代码

/**
     * 附近的人排序
     * @param lon 经度
     * @param lat 纬度
     * @return
     */
    @GetMapping("/nearbysort")
    public List<UserPosition> getVicinitySort(double lon, double lat){

        return userService.getvicinitysort(BigDecimal.valueOf(lon), BigDecimal.valueOf(lat));
    }

mybatis代码
<select id="getvicinitysort" resultMap="BaseResultMap">
    SELECT id, city, position, longitude,latitude,
        (POWER(MOD(ABS(longitude - #{longitude}),360),2) + POWER(ABS(latitude - #{latitude}),2)) AS distance
        FROM `userposition`
        ORDER BY distance LIMIT 20
  </select>
List<UserPosition> getvicinitysort(@Param("longitude") BigDecimal longitude,
                                   @Param("latitude") BigDecimal latitude);

补充,如果需要按距离排序,并返回距离的字段。可以按如下方式实现。

SELECT
    *,
    ROUND(
        6378.138 * 2 * ASIN(
            SQRT(
                POW(
                    SIN(
                        (
                            $latitude * PI() / 180 - latitude * PI() / 180
                        ) / 2
                    ),
                    2
                ) + COS($latitude * PI() / 180) * COS(latitude * PI() / 180) * POW(
                    SIN(
                        (
                            $longitude * PI() / 180 - longitude * PI() / 180
                        ) / 2
                    ),
                    2
                )
            )
        ) * 1000
    ) AS distance
FROM
    userposition
ORDER BY
    distance ASC

猜你喜欢

转载自www.cnblogs.com/EarlyBridVic/p/12557153.html