ps:如果想要获取经纬度的话,可以去百度地图拾取坐标系统 (baidu.com)
6.1 附近的人、附近的美食店铺怎么实现的
- 用mysql
- 查询性能问题,并发高、数据量大这种查询要搞垮mysql数据库
- 一般mysql查询的是一个平面矩形访问,而叫车服务要以我为中心N公里为半径的圆形覆盖
- 精准度的问题,我们知道地球不是平面坐标系,而是一个圆球,这种矩形计算在长距离计算时会有很大误差,mysql不合适
- 用GEO
- 可以解决上述问题
6.2 命令复习
GEOADD添加经纬度坐标
会出现中文乱码
- redis -cli -a 123456 – raw
GEOPOS 返回经纬度
GEOHASH返回坐标的 geohash 表示 (base32编码)
GEODIST 返回两个位置之间的距离
GEORADIUS 以给定的经纬度为中心, 返回键包含的位置元素当中, 与中心的距离不超过给定最大距离的所有位置元素。
GEORADIUSBYMEMBER 找出指定范围内的元素,中心点是由给定的位置元素决定
6.3 案例景点附近的推送功能
GEORADIUS: 以给定的经纬度为中心,找出某一半径内的元素
-
GEOService
/** * @author 晓风残月Lx * @date 2023/3/27 21:14 */ public interface GeoService { String geoAdd(); Point position(String member); String hash(String member); Distance distance(String member1, String member2); GeoResults radiusByxy(); GeoResults radiusMember(); }
-
GEOServiceImpl
import com.xfcy.service.GeoService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.geo.*; import org.springframework.data.redis.connection.RedisGeoCommands; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author 晓风残月Lx * @date 2023/3/27 21:14 */ @Service @Slf4j public class GeoServiceImpl implements GeoService { public static final String CITY = "city"; @Autowired private RedisTemplate redisTemplate; @Override public String geoAdd() { Map<String, Point> map = new HashMap<>(); map.put("白马寺", new Point(112.610356,34.728481)); map.put("龙门石窟", new Point(112.484071,34.564375)); map.put("老君山", new Point(111.663,33.75186)); map.put("白马寺的公共厕所1", new Point(112.608311,34.726809)); map.put("白马寺的公共厕所2", new Point(112.610356,34.728481)); redisTemplate.opsForGeo().add(CITY, map); return null; } @Override public Point position(String member) { // 获取经纬度坐标 List<Point> position = redisTemplate.opsForGeo().position(CITY, member); return position.get(0); } @Override public String hash(String member) { // geohash 算法生成的base32编码 List<String> hash = redisTemplate.opsForGeo().hash(CITY, member); return hash.get(0); } @Override public Distance distance(String member1, String member2) { // 获取两个给定位置之间的距离 Distance distance = redisTemplate.opsForGeo().distance(CITY, member1, member2, RedisGeoCommands.DistanceUnit.KILOMETERS); return distance; } @Override public GeoResults radiusByxy() { // 通过经纬度查找附近的,白马寺的位置 112.610356,34.728481 Circle circle = new Circle(112.610356, 34.728481, Metrics.KILOMETERS.getMultiplier()); // 返回50条 RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeCoordinates().sortDescending().limit(50); GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = redisTemplate.opsForGeo().radius(CITY, circle, args); return geoResults; } @Override public GeoResults radiusMember() { // 通过地方查找附近,洛阳白马寺为例 String member = "白马寺"; // 返回10条 RedisGeoCommands.GeoRadiusCommandArgs args = RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs().includeDistance().sortAscending().limit(10); // 半径 10 公里内 Distance distance = new Distance(10, Metrics.KILOMETERS); GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults = redisTemplate.opsForGeo().radius(CITY, member, distance, args); return geoResults; } }
-
GEOController
import com.xfcy.service.GeoService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.data.geo.Distance; import org.springframework.data.geo.GeoResults; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import org.springframework.data.geo.Point; /** * @author 晓风残月Lx * @date 2023/3/27 21:14 */ @Api(tags = "美团地图位置附近的酒店推送GEO") @Slf4j @RestController public class GeoController { @Resource private GeoService geoService; @ApiOperation("添加经纬度坐标") @RequestMapping(value = "/geoadd",method = RequestMethod.GET) public String geoAdd() { return geoService.geoAdd(); } @ApiOperation("获取经纬度坐标geopos") @RequestMapping(value = "/geopos",method = RequestMethod.GET) public Point position(String member){ return geoService.position(member); } @ApiOperation("获取经纬度生成的base32编码值geohash") @RequestMapping(value = "/geohash",method = RequestMethod.GET) public String hash(String member){ return geoService.hash(member); } @ApiOperation("获取两个给定位置之间的距离") @RequestMapping(value = "/geodist",method = RequestMethod.GET) public Distance distance(String member1, String member2){ return geoService.distance(member1,member2); } @ApiOperation("通过经纬度查找洛阳白马寺附近的") @RequestMapping(value = "/georadius",method = RequestMethod.GET) public GeoResults radiusByxy(){ return geoService.radiusByxy(); } @ApiOperation("通过地方查找附近,白马寺为例") @RequestMapping(value = "/georadiusByMember",method = RequestMethod.GET) public GeoResults radiusMember(){ return geoService.radiusMember(); } }
-
测试
下拉还有字段注意
下拉还有字段注意