puzhibing
2026-03-06 1ca66b10db05e7c9d5d653361d334f161b452c23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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<XpGeoQueryEntity> 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<XpGeoQueryEntity> 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<XpGeoQueryEntity> 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<XpGeoQueryEntity> findAll() {
        return repository.findAll();
    }
 
    @Override
    public void deleteXpGeoQueryEntity(String orderId) {
        Query query = new Query(Criteria.where("orderId").is(orderId));
        Update update = new Update().set("status", 2);
        mongoTemplate.findAndModify(query, update, XpGeoQueryEntity.class);
    }
}