From c22bae090e08333789b3339c22ec3b88f18f0a11 Mon Sep 17 00:00:00 2001 From: luyya Date: Mon, 18 Aug 2025 11:30:17 +0800 Subject: [PATCH] =?UTF-8?q?=E7=9C=81=E5=8E=85=E4=BD=8D=E7=BD=AE=E6=B1=87?= =?UTF-8?q?=E8=81=9A=E6=B7=BB=E5=8A=A0=E7=82=B9=E7=BA=BF=E9=9D=A2=E5=91=A8?= =?UTF-8?q?=E8=BE=B9=E6=9F=A5=E8=AF=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data2es/service/impl/GpsServiceImpl.java | 2 +- .../controller/ElasticSearchController.java | 15 +-- .../service/impl/CorrectGeoQueryService.java | 11 +- .../service/impl/SearchServiceImpl.java | 113 ++++++++++++------ 4 files changed, 89 insertions(+), 52 deletions(-) diff --git a/stwzhj-modules/stwzhj-data2es/src/main/java/org/dromara/data2es/service/impl/GpsServiceImpl.java b/stwzhj-modules/stwzhj-data2es/src/main/java/org/dromara/data2es/service/impl/GpsServiceImpl.java index d2fe27b8..c87cfb99 100644 --- a/stwzhj-modules/stwzhj-data2es/src/main/java/org/dromara/data2es/service/impl/GpsServiceImpl.java +++ b/stwzhj-modules/stwzhj-data2es/src/main/java/org/dromara/data2es/service/impl/GpsServiceImpl.java @@ -349,7 +349,7 @@ public class GpsServiceImpl implements IGpsService { .field("type", "text") .endObject() .startObject("deviceCode") - .field("type", "text") + .field("type", "keyword") .endObject() .startObject("infoSource") .field("type", "text") diff --git a/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/controller/ElasticSearchController.java b/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/controller/ElasticSearchController.java index c3a2effa..24893644 100644 --- a/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/controller/ElasticSearchController.java +++ b/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/controller/ElasticSearchController.java @@ -62,26 +62,15 @@ public class ElasticSearchController extends BaseController { // 1. 构建空间查询 QueryBuilder spatialQuery = geoQueryService.buildSpatialQuery(request); - // 2. 添加时间范围过滤 - BoolQueryBuilder boolQuery = QueryBuilders.boolQuery() - .filter(spatialQuery); - - if (request.getStartTime() != null && request.getEndTime() != null) { - boolQuery.filter(QueryBuilders.rangeQuery("gpsTime") - .gte(request.getStartTime()) - .lte(request.getEndTime())); - } - // 3. 执行轨迹查询(按设备去重) - List results = searchService.queryDistinctDevicesNearPoint(boolQuery,todayIndexName); + List results = searchService.queryDistinctDevicesNearPoint(spatialQuery,todayIndexName); // 4. 构建响应 return R.ok(results); - } catch (IllegalArgumentException e) { - return R.fail(e.getMessage()); } catch (Exception e) { + e.printStackTrace(); return R.fail("服务器内部错误"); } } diff --git a/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/service/impl/CorrectGeoQueryService.java b/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/service/impl/CorrectGeoQueryService.java index 0a5d7ca8..0976b3da 100644 --- a/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/service/impl/CorrectGeoQueryService.java +++ b/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/service/impl/CorrectGeoQueryService.java @@ -1,6 +1,7 @@ package org.dromara.location.service.impl; import org.dromara.location.domain.SpatialQueryRequest; +import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.geo.ShapeRelation; import org.elasticsearch.common.geo.builders.*; import org.elasticsearch.common.unit.DistanceUnit; @@ -36,10 +37,16 @@ public class CorrectGeoQueryService { if (request.getCenter() == null || request.getRadius() == null) { throw new IllegalArgumentException("点查询需要center和radius参数"); } + String distance = request.getRadius() + request.getUnit().toString().toLowerCase().charAt(0) +""; + // 使用GeoPoint确保正确顺序 + GeoPoint point = new GeoPoint( + request.getCenter().getLat(), // 纬度 + request.getCenter().getLon() // 经度 + ); return QueryBuilders.geoDistanceQuery("location") - .point(request.getCenter().getLat(), request.getCenter().getLon()) - .distance(request.getRadius(), request.getUnit().getEsUnit()); + .point(point) + .distance("3km"); } /** diff --git a/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/service/impl/SearchServiceImpl.java b/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/service/impl/SearchServiceImpl.java index 4d283538..5103007b 100644 --- a/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/service/impl/SearchServiceImpl.java +++ b/stwzhj-modules/stwzhj-location/src/main/java/org/dromara/location/service/impl/SearchServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.dromara.location.domain.EsGpsInfoVO2; import org.dromara.location.service.ISearchService; import org.elasticsearch.action.search.*; @@ -28,6 +29,10 @@ import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.io.IOException; import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -38,6 +43,7 @@ import java.util.function.Consumer; @RequiredArgsConstructor @Service +@Slf4j public class SearchServiceImpl implements ISearchService { @Resource(name = "restHighLevelClient") @@ -151,51 +157,86 @@ public class SearchServiceImpl implements ISearchService { * @param indexName 索引名称 * @return 去重后的设备列表(每个设备只返回最新的一条记录) */ - public List queryDistinctDevicesNearPoint(QueryBuilder spatialQuery, String indexName) throws IOException { - - // 构建聚合 - TermsAggregationBuilder aggregation = AggregationBuilders.terms("distinct_devices") - .field("deviceCode.keyword") - .size(100) - .subAggregation( - AggregationBuilders.topHits("latest_record") - .size(1) - .sort("gpsTime", SortOrder.DESC) - ); - - SearchSourceBuilder sourceBuilder = new SearchSourceBuilder() - .query(spatialQuery) - .aggregation(aggregation) - .size(0); - - SearchRequest request = new SearchRequest(indexName) - .source(sourceBuilder); - - // 4. 执行查询 - SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT); - - // 5. 解析聚合结果 - Terms terms = response.getAggregations().get("distinct_devices"); + public List queryDistinctDevicesNearPoint(QueryBuilder spatialQuery, String indexName) { + log.info("Final ES query: {},index={}", spatialQuery.toString(),indexName); List results = new ArrayList<>(); + try { + // 构建聚合 + TermsAggregationBuilder aggregation = AggregationBuilders.terms("distinct_devices") + .field("deviceCode") + .size(50) + .shardSize(1000) + .subAggregation( + AggregationBuilders.topHits("latest_record") + .size(1) + .sort("gpsTime", SortOrder.DESC) + ); - for (Terms.Bucket bucket : terms.getBuckets()) { - String deviceCode = bucket.getKeyAsString(); + SearchSourceBuilder sourceBuilder = new SearchSourceBuilder() + .query(spatialQuery) + .aggregation(aggregation) + .size(0); - // 获取每个设备的最新记录 - TopHits topHits = bucket.getAggregations().get("latest_record"); - SearchHit[] hits = topHits.getHits().getHits(); + SearchRequest request = new SearchRequest(indexName) + .source(sourceBuilder); - if (hits.length > 0) { - SearchHit latestHit = hits[0]; - Map source = latestHit.getSourceAsMap(); + // 4. 执行查询 + SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT); - EsGpsInfoVO2 gpsInfoVO2 = BeanUtil.copyProperties(source, EsGpsInfoVO2.class); + // 5. 解析聚合结果 + Terms terms = response.getAggregations().get("distinct_devices"); + log.info("ES response buckets: {}",terms.getBuckets().size()); - results.add(gpsInfoVO2); + + for (Terms.Bucket bucket : terms.getBuckets()) { + String deviceCode = bucket.getKeyAsString(); + + // 获取每个设备的最新记录 + TopHits topHits = bucket.getAggregations().get("latest_record"); + + SearchHit[] hits = topHits.getHits().getHits(); + + if (hits.length > 0) { + SearchHit latestHit = hits[0]; + Map source = latestHit.getSourceAsMap(); + // 解析位置信息 + List location = (List) source.get("location"); + double lon = location.get(0); + double lat = location.get(1); + EsGpsInfoVO2 gpsInfoVO2 = new EsGpsInfoVO2(); + gpsInfoVO2.setDeviceCode(deviceCode); + gpsInfoVO2.setDeviceType(source.get("deviceType").toString()); + long timestamp = Instant.parse(source.get("gpsTime").toString()).toEpochMilli(); + String isoString =source.get("gpsTime").toString(); + Instant instant = Instant.parse(isoString); + Date utcDate = Date.from(instant); + + // 方法2:使用 Hutool + 时区转换 + Date date = DateUtil.parse(isoString); + // 将时间调整为 UTC 时区 + ZonedDateTime utcZdt = date.toInstant().atZone(ZoneId.of("UTC")); + Date utcDate2 = Date.from(utcZdt.toInstant()); + + // 验证结果 + log.error("原始 UTC 时间: " + isoString); + log.error("方法1转换结果: " + utcDate); + log.error("方法2转换结果: " + utcDate2); + log.error("时间戳: " + utcDate.getTime()); + + gpsInfoVO2.setGpsTime(new Date(timestamp)); + gpsInfoVO2.setLat(lat+""); + gpsInfoVO2.setLng(lon+""); + log.info("gpsInfoVO2={}",gpsInfoVO2.toString()); + results.add(gpsInfoVO2); + } } + + return results; + }catch (Exception e){ + e.printStackTrace(); } - return results; + return results; }