23.MongoDB地理位置检索
MongoDB地理位置检索
一、查询当前坐标附近的目标
@Test
public void queryNear(){
//1.以当前位置的经纬度为圆点
GeoJsonPoint point = new GeoJsonPoint(116.404, 39.915);
//2.设置查询的范围,作为半径
Distance distance = new Distance(1,Metrics.KILOMETERS);//距离,距离的参数
//3.画圆
Circle circle = new Circle(point, distance);
//4.查询
Criteria criteria = Criteria.where("location").withinSphere(circle);
Query query = Query.query(criteria);
List<Places> places = mongoTemplate.find(query, Places.class);
//打印观察
for (Places place : places) {
System.out.println(place);
}
}
二、查询并获取距离
/**
* 查询附近并得到间距
*/
@Test
public void queryNearAndGetDistance() {
//1.以当前位置的经纬度为圆点
GeoJsonPoint geoJsonPoint = new GeoJsonPoint(116.404, 39.915);
//2.构造nearQuery对象
NearQuery nearQuery = NearQuery.near(geoJsonPoint, Metrics.KILOMETERS)
.maxDistance(1, Metrics.KILOMETERS);
//3、调用mongoTemplate的geoNear方法查询
GeoResults<Places> places = mongoTemplate.geoNear(nearQuery, Places.class);
for (GeoResult<Places> place : places) {
@NonNull Places content = place.getContent();
String address = content.getAddress();
double value = place.getDistance().getValue();
System.out.println(address+ " 距离故宫 "+ value+Metrics.KILOMETERS);
}
}
/**
* 北京市东城区南池子大街85号 距离故宫 0.5194875751391679 km
* 北京市西城区南长街38号 距离故宫 0.6557599573197416 km
* 西城区南长街20号 距离故宫 0.7784741257920857 km
* 北京市东城区南池子大街11号 距离故宫 0.7912036177839368 km
* 南河沿大街41号(近东华门、长安街) 距离故宫 0.8241175234892675 km
* 北京市东城区东华门大街91号 距离故宫 0.8714975354225662 km
* 北京市东城区东华门大街37号 距离故宫 0.9868264885628618 km
*/
三、探花搜附近的功能之上报地理位置信息
Mongo只能可以进行地理位置搜索,地理位置如何采集?
答案:移动端定位,将地理坐标发送到服务器
1、BaiDuController
package com.tanhua.server.controller;
import com.tanhua.server.service.BaiduService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@RestController
@RequestMapping("/baidu")
public class BaiduController {
@Autowired
private BaiduService baiduService;
/**
* 上报、更新地理位置位置
* 请求路径:/baidu/location
* 请求方式:post
* 请求参数:number latitude(纬度), number longitude(经度),String addrStr(位置描述)
*/
@PostMapping("/location")
public ResponseEntity updateLocation(@RequestBody Map param) {
Double longitude = Double.valueOf(param.get("longitude").toString());
Double latitude = Double.valueOf(param.get("latitude").toString());
String address = param.get("addrStr").toString();
this.baiduService.saveAndUpdateLocation(longitude, latitude,address);
return ResponseEntity.ok(null);
}
}
2、BaiDuService
package com.tanhua.server.service;
import com.tanhua.dubbo.api.UserLocationApi;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.ThreadLocalUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;
@Service
public class BaiduService {
@DubboReference
private UserLocationApi userLocationApi;
/**
* 上报地理位置
* @param longitude 经度
* @param latitude 纬度
* @param address
*/
public void saveAndUpdateLocation(Double longitude, Double latitude, String address) {
Long userId = ThreadLocalUtils.getUserId();
Boolean result = userLocationApi.saveAndUpdateLocation(userId,longitude,latitude,address);
if(!result){
throw new BusinessException(ErrorResult.error());
}
}
}
3.UserLacitonApiImpl
if (userLocation == null) {
//用户第一次上报地理信息,保存数据到数据库表
UserLocation locationInfo = new UserLocation();
locationInfo.setUserId(userId);
locationInfo.setAddress(address);
locationInfo.setCreated(System.currentTimeMillis());
locationInfo.setUpdated(System.currentTimeMillis());
locationInfo.setLastUpdated(System.currentTimeMillis());
locationInfo.setLocation(new GeoJsonPoint(longitude, latitude));
mongoTemplate.save(locationInfo);
} else {
//数据库已有过用户上传的地理信息,更新
Update update = Update.update("location", new GeoJsonPoint(longitude, latitude))
.set("address", address)
.set("updated", System.currentTimeMillis())
.set("lastUpdated", userLocation.getUpdated());
mongoTemplate.updateFirst(query, update, UserLocation.class);
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
四、搜附近
vo对象
package com.tanhua.model.vo;
import com.tanhua.model.domain.UserInfo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
//附近的人vo对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NearUserVo {
private Long userId;
private String avatar;
private String nickname;
public static NearUserVo init(UserInfo userInfo) {
NearUserVo vo = new NearUserVo();
vo.setUserId(userInfo.getId());
vo.setAvatar(userInfo.getAvatar());
vo.setNickname(userInfo.getNickname());
return vo;
}
}
TanHuaController
/**
* 搜附近
* 请求路径:/tanhua/search
* 请求方式:get
* 请求参数:String gender(性别),String distance(搜索的范围)
*/
@GetMapping("/search")
public ResponseEntity<List<NearUserVo>> queryNearUser(String gender,
@RequestParam(defaultValue = "2000") String distance) {
List<NearUserVo> list = tanHuaService.queryNearUser(gender, distance);
return ResponseEntity.ok(list);
}
TanHuaService
/**
*
*搜附近
*/
public List<NearUserVo> queryNearUser(String gender, String distance) {
//1.调用api,查询附近的人,获取他们的id
Long userId = ThreadLocalUtils.getUserId();
List<Long> userIds = userLocationApi.queryNearUser(userId,Double.valueOf(distance));
//2.判断集合是否为空
if(CollUtil.isEmpty(userIds)){
return new ArrayList<>();
}
//3.根据用户id查询用户详情
UserInfo userInfo = new UserInfo();
userInfo.setGender(gender);
Map<Long, UserInfo> userInfoMap = userInfoApi.batchQueryUserInfo(userIds, userInfo);
List<NearUserVo> vos = new ArrayList<>();
for (Long id : userIds) {
if(id == ThreadLocalUtils.getUserId()){
continue;//排除自己的id
}
UserInfo userInfo1 = userInfoMap.get(id);
if(userInfo1 != null){
NearUserVo vo = NearUserVo.init(userInfo);
vos.add(vo);
}
}
return vos;
}
UserLocationImpl
/**
*搜附近
*/
public List<Long> queryNearUser(Long userId, Double metre) {
//1.获取当前用户地理位置信息,以此为圆点
Criteria criteria = Criteria.where("userId").is(userId);
Query query = Query.query(criteria);
UserLocation location = mongoTemplate.findOne(query, UserLocation.class);
GeoJsonPoint point = location.getLocation();//圆点
//2.半径
Distance distance = new Distance(metre/1000, Metrics.KILOMETERS);
//3.画圆
Circle circle = new Circle(point, distance);
Criteria criteria1 = Criteria.where("location").withinSphere(circle);
Query query1 = Query.query(criteria1);
List<UserLocation> locationInfos = mongoTemplate.find(query1, UserLocation.class);
List<Long> userIds = CollUtil.getFieldValues(locationInfos, "userId", Long.class);
return userIds;
}