今天,日月教大家如何使用mysql根据经纬度实现距离排序搜索查询,话不多说,往下看。为了节省时间,我们在
中方式二的项目基础上修改。一、创建数据表,插入测试数据
根据上图,我们可以明显的看出,根据当前所在地按距离排序的话,应该是武汉-->黄冈-->咸宁-->九江 这样的顺序。二、创建mysql函数计算两个经纬度之间距离的 数据库函数
CREATE FUNCTION `lat_lng_distance` (lat1 FLOAT, lng1 FLOAT, lat2 FLOAT, lng2 FLOAT)RETURNS FLOATDETERMINISTICBEGIN 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;@RestControllerpublic 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;@Servicepublic 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),); 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;@Mapperpublic 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" "-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 > #{minLat} and s.latitude < #{maxLat} and s.longitude > #{minLng} and s.longitude < #{maxLng} order by distance asc </if> </select></mapper>
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 */@Datapublic class Store implements Serializable { private static final long serialVersionUID = -82774092989L; /** 店铺id */ private Long storeId; /** 店铺名称 */ private String storeName; /** 经度 */ private String longitude; /** 纬度 */ private String latitude; /** 距离 */ private String distance;}
四、启动项目,测试接口
浏览器或者postman请求:
http://localhost:8080/getStores?longitude=114.&latitude=30.594048
我们以武汉市政府的经纬度作为当前位置进行查询搜索。
可以看到,数据成功按照距离的远近进行排序返回了,distance是距离,单位km。至此,我们就简单的根据mysql函数实现了距离排序查询搜索的功能。
文章评论