mysql 实现按经纬度进行距离排序

今天,日月教大家如何使用mysql根据经纬度实现距离排序搜索查询,话不多说,往下看。
为了节省时间,我们在SpringBoot 集成 mybatis的四种方式 中方式二的项目基础上修改。

一、创建数据表,插入测试数据

在这里插入图片描述

经纬度获取方式:https://lbs.amap.com/console/show/picker
在这里插入图片描述

根据上图,我们可以明显的看出,根据当前所在地按距离排序的话,应该是
武汉–>黄冈–>咸宁–>九江 这样的顺序。

二、创建mysql函数
计算两个经纬度之间距离的 数据库函数
在这里插入图片描述

CREATE FUNCTION `lat_lng_distance` (lat1 FLOAT, lng1 FLOAT, lat2 FLOAT, lng2 FLOAT)
RETURNS FLOAT
DETERMINISTIC
BEGIN
    RETURN 6371 * 2 * ASIN(SQRT(
        POWER(SIN((lat1 - abs(lat2)) * pi()/180 / 2),
        2) + COS(lat1 * pi()/180 ) * COS(abs(lat2) *
        pi()/180) * POWER(SIN((lng1 - lng2) *
        pi()/180 / 2), 2) ));
END

三、编写测试代码

SpringBootController.java

package com.chenqi.springboot.controller;
import com.chenqi.springboot.entity.Store;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.chenqi.springboot.service.StoreService;
import java.util.List;
@RestController
public class SpringBootController {
    
    @Autowired
    StoreService storeService;
    @GetMapping("/getStores")
    public List<Store> getStores(@RequestParam("longitude") String longitude,
                                 @RequestParam("latitude") String latitude){
        return storeService.getStores(longitude,latitude);
    }
}

StoreService.java

package com.chenqi.springboot.service;
import com.chenqi.springboot.entity.Store;
import java.util.List;
public interface StoreService {
    List<Store> getStores(String longitude, String latitude);
}

StoreServiceImpl.java

package com.chenqi.springboot.service.impl;
import com.chenqi.springboot.entity.Store;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.chenqi.springboot.dao.StoreMapper;
import com.chenqi.springboot.service.StoreService;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Service
public class StoreServiceImpl implements StoreService {
    
    @Autowired
    StoreMapper storeMapper;
    @Override
    public List<Store> getStores(String longitude, String latitude) {
        //距离排序 范围500公里
        Map<String,String> map = new HashMap<String,String>();
        map = lonLatCalculation(Double.valueOf(longitude),Double.valueOf(latitude),500000);
        map.put("longitude",longitude);
        map.put("latitude",latitude);
        return storeMapper.getStores(map);
    }
    /**
     * @Author chenqi
     * @Description 根据经纬度和半径 计算
     * @Date 14:19 2019/1/2
     * @Param [longitude 经度, latitude 纬度, raidus 搜索半径 m]
     * @return java.util.Map<java.lang.String,java.lang.String>
     **/
    public static Map<String,String> lonLatCalculation(Double longitude, Double latitude, Integer raidus){
        Map<String,String> map = new HashMap<String,String>();
        // 赤道周长24901英里 1609是转换成米的系数
        Double degree = (24901 * 1609) / 360.0;
        double raidusMile = raidus;
        Double dpmLat = 1 / degree;
        Double radiusLat = dpmLat * raidusMile;
        Double minLat = latitude - radiusLat;
        Double maxLat = latitude + radiusLat;
        Double mpdLng = degree * Math.cos(latitude * (Math.PI / 180));
        Double dpmLng = 1 / mpdLng;
        Double radiusLng = dpmLng * raidusMile;
        Double minLng = longitude - radiusLng;
        Double maxLng = longitude + radiusLng;
        //return new double[] { minLat, minLng, maxLat, maxLng };
        map.put("minLat",minLat.toString());
        map.put("maxLat",maxLat.toString());
        map.put("minLng",minLng.toString());
        map.put("maxLng",maxLng.toString());
        return map;
    }
}

StoreMapper.java

package com.chenqi.springboot.dao;
import com.chenqi.springboot.entity.Store;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface StoreMapper {
    List<Store> getStores(Map<String,String> map);
}

StoreMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.chenqi.springboot.dao.StoreMapper" >
      <select id="getStores" parameterType="java.util.Map" resultType="com.chenqi.springboot.entity.Store">
        select s.store_id as storeId,
        s.store_name as storeName,
        s.longitude as longitude,
        s.latitude as latitude
        <if test="longitude != null and longitude != ''">
            , ROUND(lat_lng_distance(#{latitude}, #{longitude}, latitude, longitude), 2) as distance
        </if>
        from store s where 1=1
        <if test="longitude != null and longitude != ''">
            and s.latitude &gt; #{minLat} and s.latitude &lt; #{maxLat}
            and s.longitude &gt; #{minLng} and s.longitude &lt; #{maxLng}
            order by distance asc
        </if>
    </select>
</mapper>

Store.java

package com.chenqi.springboot.entity;
import lombok.Data;
import java.io.Serializable;
/**
 * @author chenqi
 * @version V1.0
 * @ClassName: Store
 * @Description: 店铺表
 * @Date 2019/1/13 12:37
 */
@Data
public class Store implements Serializable {
    private static final long serialVersionUID = -7541432682774092989L;
    /** 店铺id */
    private Long storeId;
    /** 店铺名称 */
    private String storeName;
    /** 经度 */
    private String longitude;
    /** 纬度 */
    private String latitude;
    /** 距离 */
    private String distance;
}

四、启动项目,测试接口
在这里插入图片描述

浏览器或者postman请求:http://localhost:8080/getStores?longitude=114.304327&latitude=30.594048
在这里插入图片描述

我们以武汉市政府的经纬度作为当前位置进行查询搜索。

在这里插入图片描述
可以看到,数据成功按照距离的远近进行排序返回了,distance是距离,单位km。
至此,我们就简单的根据mysql函数实现了距离排序查询搜索的功能。

如果该文章有帮助到您,就留言点个赞吧!您的支持与肯定是我持续更新最大的动力。

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值