mysql 5.6.1 加入了空间数据支持功能,新增了st_*相关函数,可以非常方便的计算两个地理坐标点的距离了。
SELECT
p.*FROM(
SELECT
park_info.*,st_distance(point( park_info.lng, park_info.lat ),point(116.403694,39.913828))*111195 AS distance
FROM
park_info park_info
) p
WHERE
p.distance <10000
Java实现
@Slf4j
public class DistanceUtils {/**
* 地球半径,单位 km
*/
private static final double EARTH_RADIUS =6378137;/**
* 根据经纬度,计算两点间的距离
*
* @param longitude1 第一个点的经度
* @param latitude1 第一个点的纬度
* @param longitude2 第二个点的经度
* @param latitude2 第二个点的纬度
* @return 返回距离 单位米
*/
public staticdoublegetDistance(double longitude1,double latitude1,double longitude2,double latitude2){// 纬度double lat1 = Math.toRadians(latitude1);double lat2 = Math.toRadians(latitude2);// 经度double lng1 = Math.toRadians(longitude1);double lng2 = Math.toRadians(longitude2);// 纬度之差double a = lat1 - lat2;// 经度之差double b = lng1 - lng2;// 计算两点距离的公式double s =2* Math.asin(Math.sqrt(Math.pow(Math.sin(a /2),2)+
Math.cos(lat1)* Math.cos(lat2)* Math.pow(Math.sin(b /2),2)));// 弧长乘地球半径, 返回单位: 米
s = s * EARTH_RADIUS;// return Math.round(s * 10000) / 10000;return Math.round(s *10000)/10000;}
public staticvoidmain(String[] args){double distance = DistanceUtils.getDistance(109.49081,36.596537,111.128971,37.524041);
log.info("distance={}", distance);double distance1 = DistanceUtils.getDistance(109.500603,36.594125,111.151761,37.52671);
log.info("distance={}", distance1);}}
Redis GEO实现
/**
* 添加经纬度
*
* @param key 停车场地理位置键
* @param lng 坐标
* @param lat 坐标
* @param t 停车场标示
* @return
*/
public Long addGeo(String key, Double lng, Double lat, T t){
RedisGeoCommands.GeoLocation<T> geoLocation = new RedisGeoCommands.GeoLocation<>(t, new Point(lng, lat));return redisTemplate.opsForGeo().add(key, geoLocation);}/**
* 批量添加
* @param key
* @param list
* @return
*/
public Long batchAddGeo(String key, List<RedisGeoCommands.GeoLocation<T>> list){return redisTemplate.opsForGeo().add(key, list);}/**
* 删除经纬度
*
* @param key
*/
public voidremoveGeo(String key, T... t){
redisTemplate.opsForGeo().remove(key, t);}/**
* 获取经纬度指定距离内的数据
*
* @param lng
* @param lat
* @param distance
* @param key
* @return
*/
public List<GeoResult<RedisGeoCommands.GeoLocation<T>>>getCacheListByPointAndDistance(Double lng, Double lat, Double distance, String key){
Circle circle = new Circle(new Point(lng, lat), new Distance(distance, Metrics.KILOMETERS));
RedisGeoCommands.GeoRadiusCommandArgs args =// includeCoordinates:返回结果包含坐标信息// includeDistance:返回结果包含具中心坐标距离信息// sortAscending:按照距离升序排序// sortDescending:按照距离降序排序// limit:返回结果数量限制
RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().includeCoordinates().sortAscending();
List<GeoResult<RedisGeoCommands.GeoLocation<T>>> content =
redisTemplate.opsForGeo().radius(key, circle, args).getContent();return content;}