package com.xiaopeng.operation.service.impl; import com.xiaopeng.api.model.operation.XpGeoQueryEntity; import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.operation.repository.XpGeoQueryEntityRepository; import com.xiaopeng.operation.service.IXpGeoQueryEntityService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.geo.*; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; import org.springframework.stereotype.Service; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.stream.Collectors; /** * MongoDB 地理查询服务实现类 */ @Service public class XpGeoQueryEntityServiceImpl implements IXpGeoQueryEntityService { @Autowired private XpGeoQueryEntityRepository repository; @Autowired private MongoTemplate mongoTemplate; /** * 通过经纬度查询固定范围500米内、一周内、指定时段的数据 * @param longitude 经度 * @param latitude 纬度 * @param time 时段(格式:HH-HH,例如:19-20) * @return 符合条件的实体列表 */ @Override public List findByLocationWithin500MetersAndLastWeekAndStatusGreater( double longitude, double latitude, String time ) { // // 计算一周前的时间 Calendar calendar = Calendar.getInstance(); calendar.setTime(new Date()); calendar.add(Calendar.DAY_OF_YEAR, -7); Long startTime = calendar.getTime().getTime(); // // 1. 创建查询点 // Point referencePoint = new Point(longitude, latitude); // // // 2. 构建 NearQuery - 完全使用 NearQuery 的 API // NearQuery nearQuery = NearQuery.near(referencePoint, Metrics.KILOMETERS) // .maxDistance(0.5) // 转成公里 // .spherical(true); // // // // 3.时间>startTime time = time参数 // // 3. 创建额外的查询条件 // Query query = new Query(); // query.addCriteria(Criteria.where("timestamp").gte(startTime)); // query.addCriteria(Criteria.where("time").is(time)); // // // 将 NearQuery 和额外的查询条件合并 // nearQuery.query(query); // // // // 4. 执行查询 - 明确指定集合名 // GeoResults geoResults = mongoTemplate.geoNear( // nearQuery, // XpGeoQueryEntity.class, // "xp_geo_query_entity" // 明确指定集合名,避免映射错误 // ); // // // 5. 提取结果 // return geoResults.getContent().stream() // .map(geoResult -> geoResult.getContent()) // .collect(Collectors.toList()); //找到中心点 GeoJsonPoint geoJsonPoint = new GeoJsonPoint(longitude, latitude); //构造半径 Distance distanceR = new Distance(0.5, Metrics.KILOMETERS); //画圆 Circle circle = new Circle(geoJsonPoint, distanceR); // 构造query对象 Query query = Query.query(Criteria.where("location").withinSphere(circle)); query.addCriteria(Criteria.where("timestamp").gte(startTime)); query.addCriteria(Criteria.where("time").is(time)); List xpGeoQueryEntities = mongoTemplate.find(query, XpGeoQueryEntity.class); return xpGeoQueryEntities; } /** * 保存地理查询实体 * @param entity 地理查询实体 * @return 保存后的实体 */ @Override public XpGeoQueryEntity save(XpGeoQueryEntity entity) { return repository.save(entity); } @Override public XpGeoQueryEntity updateByOrderId(String orderId) { Query query = new Query(Criteria.where("orderId").is(orderId)); XpGeoQueryEntity xpGeoQueryEntity = mongoTemplate.findOne(query, XpGeoQueryEntity.class); Long timestamp = xpGeoQueryEntity.getTimestamp(); long time = new Date().getTime(); // 计算2个时间的秒数差 long seconds = (time- timestamp) / 1000; Update update = new Update().set("seconds", seconds).set("status", 1); if(xpGeoQueryEntity.getStatus()==0){ mongoTemplate.findAndModify(query, update, XpGeoQueryEntity.class); } return null; } /** * 根据ID查询实体 * @param id 实体ID * @return 实体 */ @Override public XpGeoQueryEntity findById(String id) { return repository.findById(id).orElse(null); } /** * 删除实体 * @param id 实体ID */ @Override public void deleteById(String id) { repository.deleteById(id); } /** * 查询所有实体 * @return 实体列表 */ @Override public List findAll() { return repository.findAll(); } }