Просмотр исходного кода

Merge branch 'master' of http://120.25.74.229:8003/chenfangchao/es-track-analysis into chenfangchao

chenfangchao лет назад: 2
Родитель
Сommit
d7ec82aab2

+ 68 - 0
fusion-analysis/pom.xml

@@ -14,14 +14,52 @@
     <properties>
         <maven.compiler.source>8</maven.compiler.source>
         <maven.compiler.target>8</maven.compiler.target>
+        <elasticsearch.version>7.16.2</elasticsearch.version>
     </properties>
 
     <dependencies>
         <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <version>2.7.6</version>
+        </dependency>
+
+        <dependency>
             <groupId>cn.com.taiji</groupId>
             <artifactId>es-track-common</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
+
+        <!-- es -->
+        <dependency>
+            <groupId>org.elasticsearch</groupId>
+            <artifactId>elasticsearch</artifactId>
+            <version>${elasticsearch.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-client</artifactId>
+            <version>${elasticsearch.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.elasticsearch.client</groupId>
+            <artifactId>elasticsearch-rest-high-level-client</artifactId>
+            <version>${elasticsearch.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-core</artifactId>
+            <version>2.14.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.14.2</version>
+        </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>
@@ -42,5 +80,35 @@
         </dependency>
     </dependencies>
 
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.1.1.RELEASE</version>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <version>3.1.0</version>
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <warName>${project.artifactId}</warName>
+                </configuration>
+            </plugin>
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
 
 </project>

+ 91 - 0
fusion-analysis/src/main/java/cn/com/taiji/config/EsClientConfiguration.java

@@ -0,0 +1,91 @@
+package cn.com.taiji.config;
+
+import org.apache.http.HttpHost;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestHighLevelClient;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
+
+/**
+ * @ClassNmae EsClientConfiguration
+ * @Description es连接类
+ * @Author suhh
+ * @Date2021/9/417:25
+ * @Version 1.0
+ **/
+@Configuration
+public class EsClientConfiguration {
+    @Value("${taiji.elasticsearch.rest.uris}")
+    private String[] esUris;
+    @Value("${taiji.elasticsearch.rest.connection-timeout}")
+    /**
+     * 连接超时时间
+     */
+    private int connectTimeOut;
+    @Value("${taiji.elasticsearch.rest.max-connection}")
+    /**
+     * 最大连接数
+     */
+    private int maxConnection;
+    @Value("${taiji.elasticsearch.rest.username}")
+    /**
+     *  用户名
+     */
+    private String userName;
+    @Value("${taiji.elasticsearch.rest.password}")
+    /**
+     * 密码
+     */
+    private String password;
+
+    @Bean
+    public RestHighLevelClient client() {
+
+        HttpHost[] httpHosts = new HttpHost[esUris.length];
+        //将地址转换为http主机数组,未配置端口则采用默认9200端口,配置了端口则用配置的端口
+        for (int i = 0; i < httpHosts.length; i++) {
+            if (!StringUtils.isEmpty(esUris[i])) {
+                if (esUris[i].contains(":")) {
+                    String[] uris = esUris[i].split(":");
+                    httpHosts[i] = new HttpHost(uris[0], Integer.parseInt(uris[1]), "http");
+                } else {
+                    httpHosts[i] = new HttpHost(esUris[i], 9200, "http");
+                }
+            }
+        }
+        //判断,如果未配置用户名,则进行无用户名密码连接,配置了用户名,则进行用户名密码连接
+        if (StringUtils.isEmpty(userName)) {
+            RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(httpHosts));
+            return client;
+        } else {
+
+            final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+            credentialsProvider.setCredentials(AuthScope.ANY,
+                    //es账号密码
+                    new UsernamePasswordCredentials(userName, password));
+            RestHighLevelClient client = new RestHighLevelClient(
+                    RestClient.builder(httpHosts)
+                            .setHttpClientConfigCallback((httpClientBuilder) -> {
+                                httpClientBuilder.setMaxConnTotal(maxConnection);
+                                httpClientBuilder.disableAuthCaching();
+                                httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
+
+                                return httpClientBuilder;
+                            })
+                            .setRequestConfigCallback(builder -> {
+                                builder.setConnectTimeout(connectTimeOut);
+
+                                return builder;
+                            })
+
+            );
+            return client;
+        }
+    }
+}

+ 46 - 0
fusion-analysis/src/main/java/cn/com/taiji/constants/EsIndexConstants.java

@@ -0,0 +1,46 @@
+package cn.com.taiji.constants;
+
+/**
+ * @author chenfangchao
+ * @title: EsIndexConstants
+ * @projectName es-track-analysis
+ * @description: TODO
+ * @date 2023/2/6 10:54 AM
+ */
+public class EsIndexConstants {
+
+    /**
+     * 融合
+     */
+    public static final String INDEX_SEAT_REALTIMETRAJECTORY = "index_seat_realtimetrajectory_";
+
+    /**
+     * 融合
+     */
+    public static final String INDEX_SEAT_REALTIMETRAJECTORY_TEST = "index_seat_realtimetrajectory_test_";
+
+    /**
+     * 北斗
+     */
+    public static final String INDEX_SEAT_TRACK_BEIDOU = "index_seat_beidou_dynamic_ship_track_";
+
+    /**
+     * AIS
+     */
+    public static final String INDEX_SEAT_TRACK_AIS = "index_seat_ztpt_dynamic_ais_ship_track_";
+
+    /**
+     * 海兰信一级融合
+     */
+    public static final String INDEX_SEAT_HLX_FUSION_SHIP = "index_seat_hlx_zww_dynamic_fusion_ship_";
+
+    /**
+     * 天奥雷达
+     */
+    public static final String INDEX_SEAT_TRACK_RADAR = "index_seat_tianao_radar_fusion_ship_track_";
+
+    /**
+     * 中远海雷达
+     */
+    public static final String INDEX_SEAT_TRACK_ZYH = "index_seat_zyh_radar_track_";
+}

+ 84 - 0
fusion-analysis/src/main/java/cn/com/taiji/controller/FusionAnalysisController.java

@@ -1,8 +1,17 @@
 package cn.com.taiji.controller;
 
+import cn.com.taiji.domain.FusionQuery;
+import cn.com.taiji.service.FusionAnalysisService;
+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 javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.text.ParseException;
+
 /**
  * @author xhl
  * @date 2023/2/6
@@ -10,4 +19,79 @@ import org.springframework.web.bind.annotation.RestController;
 @RequestMapping("/es/fusion/analysis")
 @RestController
 public class FusionAnalysisController {
+
+    @Resource
+    private FusionAnalysisService fusionAnalysisService;
+
+    /**
+     * 轨迹融合-航速航向异常波动-识别融合数据率波动问题
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    @PostMapping("excel/one")
+    public void fusionAnalysisExcelOne(@RequestBody FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        fusionAnalysisService.fusionAnalysisExcelOne(query,response);
+    }
+
+    /**
+     * 虚假外推数据-虚假推送问题
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    @PostMapping("excel/two")
+    public void fusionAnalysisExcelTwo(@RequestBody FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        fusionAnalysisService.fusionAnalysisExcelTwo(query,response);
+    }
+
+    /**
+     * 遗漏融合-天奥轨迹数据遗漏
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    @PostMapping("/tianao/excel")
+    public void tianAoLeaveOutExcel(@RequestBody FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        fusionAnalysisService.tianAoLeaveOutExcel(query,response);
+    }
+
+    /**
+     * 遗漏融合-北斗轨迹数据遗漏
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    @PostMapping("/beidou/excel")
+    public void beiDouLeaveOutExcel(@RequestBody FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        fusionAnalysisService.beiDouLeaveOutExcel(query,response);
+    }
+
+    /**
+     * 遗漏融合-海兰信1级融合轨迹数据遗漏
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    @PostMapping("/hlxyjrh/excel")
+    public void hlxyjrhLeaveOutExcel(@RequestBody FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        fusionAnalysisService.hlxyjrhLeaveOutExcel(query,response);
+    }
+
+    /**
+     * 错误融合-天奥静态数据与动态轨迹融合
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    @PostMapping("/tianao/static/excel")
+    public void tianaoStaticOrDynamicLeaveOutExcel(@RequestBody FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        fusionAnalysisService.tianaoStaticOrDynamicLeaveOutExcel(query,response);
+    }
 }

+ 42 - 3
fusion-analysis/src/main/java/cn/com/taiji/domain/FusionData.java

@@ -7,7 +7,6 @@ import lombok.Data;
  * @author xhl
  * @date 2023/2/6
  */
-@Data
 public class FusionData {
 
     /**
@@ -23,9 +22,9 @@ public class FusionData {
     private String startTime;
 
     /**
-     * 结束时间
+     * 批次结束时间
      */
-    @ExcelProperty(index = 2,value = "结束时间")
+    @ExcelProperty(index = 2,value = "批次结束时间")
     private String endTime;
 
     /**
@@ -39,4 +38,44 @@ public class FusionData {
      */
     @ExcelProperty(index = 4,value = "波动次数")
     private Integer fluctuateNumber;
+
+    public String getMergeTarget() {
+        return mergeTarget;
+    }
+
+    public void setMergeTarget(String mergeTarget) {
+        this.mergeTarget = mergeTarget;
+    }
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public Long getTrackCount() {
+        return trackCount;
+    }
+
+    public void setTrackCount(Long trackCount) {
+        this.trackCount = trackCount;
+    }
+
+    public Integer getFluctuateNumber() {
+        return fluctuateNumber;
+    }
+
+    public void setFluctuateNumber(Integer fluctuateNumber) {
+        this.fluctuateNumber = fluctuateNumber;
+    }
 }

+ 24 - 1
fusion-analysis/src/main/java/cn/com/taiji/domain/FusionQuery.java

@@ -6,7 +6,6 @@ import lombok.Data;
  * @author xhl
  * @date 2023/2/6
  */
-@Data
 public class FusionQuery {
 
     private String startTime;
@@ -14,4 +13,28 @@ public class FusionQuery {
     private String endTime;
 
     private Integer pageSize;
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public Integer getPageSize() {
+        return pageSize;
+    }
+
+    public void setPageSize(Integer pageSize) {
+        this.pageSize = pageSize;
+    }
 }

+ 95 - 0
fusion-analysis/src/main/java/cn/com/taiji/domain/LeaveOutData.java

@@ -0,0 +1,95 @@
+package cn.com.taiji.domain;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+/**
+ * @author xhl
+ * @date 2023/2/7
+ */
+
+public class LeaveOutData {
+    /**
+     * 批次号
+     */
+    @ExcelProperty(index = 0,value = "批次号")
+    private String batchNumber;
+
+    /**
+     * 批次开始时间
+     */
+    @ExcelProperty(index = 1,value = "批次开始时间")
+    private String startTime;
+
+    /**
+     * 批次结束时间
+     */
+    @ExcelProperty(index = 2,value = "批次结束时间")
+    private String endTime;
+
+    /**
+     * 原始轨迹点数
+     */
+    @ExcelProperty(index = 3,value = "原始轨迹点数")
+    private Long originalCount;
+
+    /**
+     * 融合轨迹批次号
+     */
+    @ExcelProperty(index = 4,value = "融合轨迹批次号")
+    private String mergeTarget;
+
+    /**
+     * 融合轨迹中出现的次数
+     */
+    @ExcelProperty(index = 5,value = "融合轨迹中出现的次数")
+    private Long trackCount;
+
+    public String getBatchNumber() {
+        return batchNumber;
+    }
+
+    public void setBatchNumber(String batchNumber) {
+        this.batchNumber = batchNumber;
+    }
+
+    public String getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(String startTime) {
+        this.startTime = startTime;
+    }
+
+    public String getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(String endTime) {
+        this.endTime = endTime;
+    }
+
+    public Long getOriginalCount() {
+        return originalCount;
+    }
+
+    public void setOriginalCount(Long originalCount) {
+        this.originalCount = originalCount;
+    }
+
+    public String getMergeTarget() {
+        return mergeTarget;
+    }
+
+    public void setMergeTarget(String mergeTarget) {
+        this.mergeTarget = mergeTarget;
+    }
+
+    public Long getTrackCount() {
+        return trackCount;
+    }
+
+    public void setTrackCount(Long trackCount) {
+        this.trackCount = trackCount;
+    }
+}

+ 39 - 0
fusion-analysis/src/main/java/cn/com/taiji/domain/StaticOrDynamicData.java

@@ -0,0 +1,39 @@
+package cn.com.taiji.domain;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+/**
+ * @author xhl
+ * @date 2023/2/7
+ */
+public class StaticOrDynamicData {
+
+    /**
+     * 融合批次号
+     */
+    @ExcelProperty(index = 0,value = "融合批次号")
+    private String mergeTarget;
+
+    /**
+     * 天奥批次号
+     */
+    @ExcelProperty(index = 1,value = "天奥批次号")
+    private String batchNumber;
+
+    public String getMergeTarget() {
+        return mergeTarget;
+    }
+
+    public void setMergeTarget(String mergeTarget) {
+        this.mergeTarget = mergeTarget;
+    }
+
+    public String getBatchNumber() {
+        return batchNumber;
+    }
+
+    public void setBatchNumber(String batchNumber) {
+        this.batchNumber = batchNumber;
+    }
+}

+ 35 - 0
fusion-analysis/src/main/java/cn/com/taiji/domain/dto/LeaceOutDto.java

@@ -0,0 +1,35 @@
+package cn.com.taiji.domain.dto;
+
+import lombok.Data;
+
+/**
+ * @author xhl
+ * @date 2023/2/7
+ */
+public class LeaceOutDto {
+    /**
+     * 批次号
+     */
+    private String batchNumber;
+
+    /**
+     * 数量
+     */
+    private Long count;
+
+    public String getBatchNumber() {
+        return batchNumber;
+    }
+
+    public void setBatchNumber(String batchNumber) {
+        this.batchNumber = batchNumber;
+    }
+
+    public Long getCount() {
+        return count;
+    }
+
+    public void setCount(Long count) {
+        this.count = count;
+    }
+}

+ 48 - 1
fusion-analysis/src/main/java/cn/com/taiji/service/FusionAnalysisService.java

@@ -16,6 +16,53 @@ public interface FusionAnalysisService {
      * 识别融合数据率波动问题
      * @param query
      * @param response
+     * @throws IOException
+     * @throws ParseException
      */
-    void fusionMergeTimeExcelExport(FusionQuery query, HttpServletResponse response) throws IOException, ParseException;
+    void fusionAnalysisExcelOne(FusionQuery query, HttpServletResponse response) throws IOException, ParseException;
+
+    /**
+     * 虚假推送问题
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    void fusionAnalysisExcelTwo(FusionQuery query, HttpServletResponse response) throws IOException, ParseException;
+
+    /**
+     * 天奥轨迹数据遗漏
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    void tianAoLeaveOutExcel(FusionQuery query, HttpServletResponse response) throws IOException, ParseException;
+
+    /**
+     * 北斗轨迹数据遗漏
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    void beiDouLeaveOutExcel(FusionQuery query, HttpServletResponse response) throws IOException, ParseException;
+
+    /**
+     * 海兰信1级融合轨迹数据遗漏
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    void hlxyjrhLeaveOutExcel(FusionQuery query, HttpServletResponse response) throws IOException, ParseException;
+
+    /**
+     * 天奥静态数据与动态轨迹融合
+     * @param query
+     * @param response
+     * @throws IOException
+     * @throws ParseException
+     */
+    void tianaoStaticOrDynamicLeaveOutExcel(FusionQuery query, HttpServletResponse response) throws IOException, ParseException;
 }

+ 773 - 49
fusion-analysis/src/main/java/cn/com/taiji/service/impl/FusionAnalysisServiceImpl.java

@@ -2,21 +2,33 @@ package cn.com.taiji.service.impl;
 
 import cn.com.taiji.domain.FusionData;
 import cn.com.taiji.domain.FusionQuery;
+import cn.com.taiji.domain.LeaveOutData;
+import cn.com.taiji.domain.StaticOrDynamicData;
+import cn.com.taiji.domain.dto.LeaceOutDto;
 import cn.com.taiji.service.FusionAnalysisService;
 import cn.com.taiji.utils.DateUtils;
+import cn.hutool.core.io.LineHandler;
 import com.alibaba.excel.EasyExcel;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.http.client.config.RequestConfig;
+import org.elasticsearch.action.index.IndexRequest;
 import org.elasticsearch.action.search.SearchRequest;
 import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.client.HttpAsyncResponseConsumerFactory;
 import org.elasticsearch.client.RequestOptions;
+import org.elasticsearch.client.RestClientBuilder;
 import org.elasticsearch.client.RestHighLevelClient;
+import org.elasticsearch.core.TimeValue;
 import org.elasticsearch.index.query.BoolQueryBuilder;
 import org.elasticsearch.index.query.QueryBuilders;
 import org.elasticsearch.search.SearchHit;
 import org.elasticsearch.search.SearchHits;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.elasticsearch.search.aggregations.Aggregations;
+import org.elasticsearch.search.aggregations.bucket.terms.ParsedDoubleTerms;
 import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
 import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
@@ -30,92 +42,804 @@ import org.springframework.stereotype.Service;
 import javax.servlet.http.HttpServletResponse;
 
 import java.io.IOException;
+import java.lang.reflect.Field;
 import java.net.URLEncoder;
 import java.text.ParseException;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+
+import static cn.com.taiji.constants.EsIndexConstants.*;
 
-import static cn.com.taiji.constants.EsIndexConstants.INDEX_SEAT_REALTIMETRAJECTORY;
 
 /**
  * @author xhl
  * @date 2023/2/6
  */
-@Slf4j
 @Service
 public class FusionAnalysisServiceImpl implements FusionAnalysisService {
 
+    private static final RequestOptions COMMON_OPTIONS;
+
+    static {
+        RequestConfig requestConfig = RequestConfig.custom()
+                .setConnectTimeout(5000)
+                .setSocketTimeout(60000)
+                .build();
+        RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
+        builder.setRequestConfig(requestConfig).setHttpAsyncResponseConsumerFactory(
+                // 设置查询内容大小限制,默认100 * 1024 * 1024
+                new HttpAsyncResponseConsumerFactory.HeapBufferedResponseConsumerFactory(5*1024 * 1024 * 1024)
+        );
+        COMMON_OPTIONS = builder.build();
+    }
+
     @Autowired
     private RestHighLevelClient client;
 
     @Override
-    public void fusionMergeTimeExcelExport(FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+    public void fusionAnalysisExcelOne(FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
         List<FusionData> list = new ArrayList<>();
-        String time = DateUtils.format(new Date(),"yyyy-MM-dd");
+        Date startTime = DateUtils.parse(query.getStartTime(),"yyyy-MM-dd");
+        String time = DateUtils.format(startTime,"yyyy-MM-dd");
         SearchRequest request = new SearchRequest(INDEX_SEAT_REALTIMETRAJECTORY+time);
         // 构建查询条件
         BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
         SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
         boolQueryBuilder.filter(QueryBuilders.rangeQuery("mergeTime").gte(query.getStartTime()).lte(query.getEndTime()));
         searchSourceBuilder.query(boolQueryBuilder);
-        TermsAggregationBuilder aggBuilder = AggregationBuilders.terms("ship_field_agg")
-                .field("mergeTarget")
+//        TermsAggregationBuilder aggBuilder = AggregationBuilders.terms("ship_field_agg")
+//                .field("mergeTarget")
+//                .size(query.getPageSize())
+//                .subAggregation(
+//                        AggregationBuilders.topHits("ship_field_agg_top1")
+//                                .size(100)
+//                                .sort(
+//                                        SortBuilders.fieldSort("mergeTime").order(SortOrder.ASC)
+//                                )
+//                );
+        searchSourceBuilder
+                .trackTotalHits(true)
+                .sort(SortBuilders.fieldSort("mergeTime").order(SortOrder.ASC))
+//                .aggregation(aggBuilder)
                 .size(query.getPageSize())
-                .subAggregation(
-                        AggregationBuilders.topHits("ship_field_agg_top1")
-                                .size(query.getPageSize())
-                                .sort(
-                                        SortBuilders.fieldSort("mergeTime").order(SortOrder.ASC)
-                                )
-                );
-        searchSourceBuilder.sort("merge_time", SortOrder.ASC)
+                .timeout(TimeValue.timeValueHours(1L))
+                .timeout(TimeValue.timeValueMinutes(30L))
+                .timeout(TimeValue.timeValueSeconds(500L));
+        request.source(searchSourceBuilder);
+        SearchResponse search = client.search(request, COMMON_OPTIONS);
+        SearchHits searchHits = search.getHits();
+        SearchHit[] hits = searchHits.getHits();
+        List<Map<String, Object>> inList = new ArrayList<Map<String, Object>>();
+        List<Map<String, Object>> outList = new ArrayList<Map<String, Object>>();
+        for (SearchHit hit : hits) {
+            Map<String, Object> map = hit.getSourceAsMap();
+            inList.add(map);
+        }
+        outList = change(inList, "mergeTarget", outList);
+        outList.forEach(map->{
+            JSONObject maps = JSONObject.parseObject(JSON.toJSONString(map));
+//            JSONObject maps = new JSONObject();
+//            Iterator it = map.keySet().iterator();
+//            while (it.hasNext()) {
+//                String key = (String) it.next();
+//                maps.put(key, map.get(key));
+//            }
+            JSONArray jsonArray =JSONArray.parseArray(maps.getString("array"));
+            if (jsonArray.size()>0){
+                FusionData data = new FusionData();
+                Integer num = 0;
+                for (int i = 0; i < jsonArray.size(); i++) {
+                    if (i<jsonArray.size()-1){
+                        JSONObject job = jsonArray.getJSONObject(i);
+                        JSONObject job2 = jsonArray.getJSONObject(i+1);
+                        Date date = null;
+                        Date date2 = null;
+                        try {
+                            date = DateUtils.parse(job.get("mergeTime").toString(),"yyyy-MM-dd HH:mm:ss.SSS");
+                            date2 = DateUtils.parse(job2.get("mergeTime").toString(),"yyyy-MM-dd HH:mm:ss.SSS");
+                        } catch (ParseException e) {
+                            e.printStackTrace();
+                        }
+                        Long interval = date2.getTime()-date.getTime();
+                        if (interval>6500L){
+                            num++;
+                        }
+                    }
+                }
+                if (num>0){
+                    JSONObject sourceItem = jsonArray.getJSONObject(0);
+                    JSONObject sourceItem2 = jsonArray.getJSONObject(jsonArray.size()-1);
+                    data.setMergeTarget(sourceItem.getString("mergeTarget"));
+                    data.setTrackCount((long) jsonArray.size());
+                    data.setStartTime(sourceItem.getString("mergeTime"));
+                    data.setEndTime(sourceItem2.getString("mergeTime"));
+                    data.setFluctuateNumber(num);
+                    list.add(data);
+                }
+            }
+        });
+//        Aggregations aggregations = search.getAggregations();
+//        ParsedStringTerms aggregation = aggregations.get("ship_field_agg");
+//        for (Terms.Bucket bucket : aggregation.getBuckets()) {
+//            FusionData data = new FusionData();
+//            ParsedTopHits topHits = bucket.getAggregations().get("ship_field_agg_top1");
+//            SearchHits searchHits = topHits.getHits();
+//            Long value = searchHits.getTotalHits().value;
+//            SearchHit[] hits = searchHits.getHits();
+//            Integer num = 0;
+//            for (int i = 0; i < hits.length; i++) {
+//                if (i != hits.length-1){
+//                    Map<String, Object> map = hits[i].getSourceAsMap();
+//                    Map<String, Object> map2 = hits[i+1].getSourceAsMap();
+//                    Date date = DateUtils.parse(map.get("mergeTime").toString(),"yyyy-MM-dd");
+//                    Date date2 = DateUtils.parse(map2.get("mergeTime").toString(),"yyyy-MM-dd");
+//                    Long interval = date2.getTime()-date.getTime();
+//                    if (interval>6500L){
+//                        num++;
+//                    }
+//                }
+//            }
+//            if (num>0){
+//                JSONObject sourceItem = JSONObject.parseObject(hits[0].getSourceAsString());
+//                JSONObject sourceItem2 = JSONObject.parseObject(hits[value.intValue()-1].getSourceAsString());
+//                data.setMergeTarget(sourceItem.getString("mergeTarget"));
+//                data.setTrackCount(value);
+//                data.setStartTime(sourceItem.getString("mergeTime"));
+//                data.setEndTime(sourceItem2.getString("mergeTime"));
+//                data.setFluctuateNumber(num);
+//                list.add(data);
+//            }
+//        }
+        try {
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+            String fileName = URLEncoder.encode("识别融合数据率波动问题", "UTF-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
+            EasyExcel.write(response.getOutputStream(), FusionData.class).sheet("识别融合数据率波动问题")
+                    .doWrite(list);
+        } catch (Exception e) {
+            // 重置response
+            System.out.println("导出识别融合数据率波动问题excel失败:{}" + e.getMessage() + e);
+        }
+    }
+
+    @Override
+    public void fusionAnalysisExcelTwo(FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+
+        List<FusionData> list = new ArrayList<>();
+        Date startTime = DateUtils.parse(query.getStartTime(),"yyyy-MM-dd");
+        String time = DateUtils.format(startTime,"yyyy-MM-dd");
+        SearchRequest request = new SearchRequest(INDEX_SEAT_REALTIMETRAJECTORY+time);
+        // 构建查询条件
+        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+        boolQueryBuilder.filter(QueryBuilders.rangeQuery("mergeTime").gte(query.getStartTime()).lte(query.getEndTime()));
+        searchSourceBuilder.query(boolQueryBuilder);
+//        TermsAggregationBuilder aggBuilder = AggregationBuilders.terms("ship_field_agg")
+//                .field("mergeTarget")
+//                .size(query.getPageSize())
+//                .subAggregation(
+//                        AggregationBuilders.terms("ship_field_agg_one")
+//                                .field("targetCourse")
+//                                .size(query.getPageSize())
+//                                .subAggregation(
+//                                        AggregationBuilders.terms("ship_field_agg_two")
+//                                                .field("targetSpeed")
+//                                                .size(query.getPageSize())
+//                                                .subAggregation(AggregationBuilders.topHits("ship_field_agg_top1")
+//                                                        .size(100)
+//                                                        .sort(
+//                                                                SortBuilders.fieldSort("mergeTime").order(SortOrder.ASC)
+//                                                        ))
+//                                )
+//                );
+        searchSourceBuilder
                 .trackTotalHits(true)
-                .aggregation(aggBuilder)
-                .size(query.getPageSize());
+//                .aggregation(aggBuilder)
+                .size(query.getPageSize())
+                .sort(SortBuilders.fieldSort("mergeTime").order(SortOrder.ASC))
+                .timeout(TimeValue.timeValueHours(1L))
+                .timeout(TimeValue.timeValueMinutes(30L))
+                .timeout(TimeValue.timeValueSeconds(500L));
         request.source(searchSourceBuilder);
-        SearchResponse search = client.search(request, RequestOptions.DEFAULT);
-        Aggregations aggregations = search.getAggregations();
-        ParsedStringTerms aggregation = aggregations.get("ship_field_agg");
-        for (Terms.Bucket bucket : aggregation.getBuckets()) {
+        SearchResponse search = client.search(request, COMMON_OPTIONS);
+        SearchHits searchHits = search.getHits();
+        SearchHit[] hits = searchHits.getHits();
+        List<Map<String, Object>> inList = new ArrayList<Map<String, Object>>();
+        List<Map<String, Object>> outList = new ArrayList<Map<String, Object>>();
+        for (SearchHit hit : hits) {
+            Map<String, Object> map = hit.getSourceAsMap();
+            inList.add(map);
+        }
+        outList = change(inList, "mergeTarget", outList);
+        outList.forEach(map->{
+            JSONObject maps = JSONObject.parseObject(JSON.toJSONString(map));
+//            JSONObject maps = new JSONObject();
+//            Iterator it = map.keySet().iterator();
+//            while (it.hasNext()) {
+//                String key = (String) it.next();
+//                maps.put(key, map.get(key));
+//            }
             FusionData data = new FusionData();
-            ParsedTopHits topHits = bucket.getAggregations().get("ship_field_agg_top1");
-            SearchHits searchHits = topHits.getHits();
-            Long value = searchHits.getTotalHits().value;
-            SearchHit[] hits = searchHits.getHits();
-            JSONObject sourceItem = JSONObject.parseObject(hits[0].getSourceAsString());
-            JSONObject sourceItem2 = JSONObject.parseObject(hits[value.intValue()-1].getSourceAsString());
-            data.setMergeTarget(sourceItem.getString("mergeTarget"));
-            data.setTrackCount(value);
-            data.setStartTime(sourceItem.getString("mergeTime"));
-            data.setEndTime(sourceItem2.getString("mergeTime"));
+            JSONArray jsonArray = JSONArray.parseArray(maps.getString("array"));
             Integer num = 0;
-            for (int i = 0; i < hits.length; i++) {
-                if (i != hits.length-1){
-                    Map<String, Object> map = hits[i].getSourceAsMap();
-                    Map<String, Object> map2 = hits[i+1].getSourceAsMap();
-                    Date date = DateUtils.parse(map.get("merge_time").toString(),"yyyy-MM-dd");
-                    Date date2 = DateUtils.parse(map2.get("merge_time").toString(),"yyyy-MM-dd");
-                    Long interval = date2.getTime()-date.getTime();
-                    if (interval>6500L){
-                        num++;
+            if (jsonArray.size() > 0) {
+                for (int i = 0; i < jsonArray.size(); i++) {
+                    JSONObject job = jsonArray.getJSONObject(i);
+                    for (int j = 0; j+i < jsonArray.size(); j++){
+                        JSONObject job2 = jsonArray.getJSONObject(j+i);
+                        if (job.getString("targetCourse").equals(job2.getString("targetCourse"))){
+                            if (job.getString("targetSpeed").equals(job2.getString("targetSpeed"))){
+                                if (num==3){
+                                    if (data.getFluctuateNumber()!=null){
+                                        data.setFluctuateNumber(data.getFluctuateNumber()+1);
+                                    }else {
+                                        data.setFluctuateNumber(1);
+                                    }
+                                    data.setMergeTarget(maps.getString("text"));
+                                    data.setTrackCount((long) jsonArray.size());
+                                    data.setStartTime(jsonArray.getJSONObject(0).getString("mergeTime"));
+                                    data.setEndTime(jsonArray.getJSONObject(jsonArray.size()-1).getString("mergeTime"));
+                                    list.add(data);
+                                    num =0;
+                                }
+                                Date date = null;
+                                Date date2 = null;
+                                try {
+                                    date = DateUtils.parse(job.get("mergeTime").toString(),"yyyy-MM-dd HH:mm:ss.SSS");
+                                    date2 = DateUtils.parse(job2.get("mergeTime").toString(),"yyyy-MM-dd HH:mm:ss.SSS");
+                                } catch (ParseException e) {
+                                    e.printStackTrace();
+                                }
+                                Long interval = dateUtils(date.getTime(),date2.getTime());
+                                if (interval<6500L){
+                                    num++;
+                                }
+                            }
+                        }
                     }
                 }
             }
-            data.setFluctuateNumber(num);
-            list.add(data);
+        });
+//        Aggregations aggregations = search.getAggregations();
+//        ParsedStringTerms aggregation = aggregations.get("ship_field_agg");
+//        for (Terms.Bucket bucket : aggregation.getBuckets()) {
+//            FusionData data = new FusionData();
+//            ParsedStringTerms terms = bucket.getAggregations().get("ship_field_agg_one");
+//            Integer num = 0;
+//            for (Terms.Bucket buc : terms.getBuckets()){
+//                ParsedDoubleTerms termsTwo = buc.getAggregations().get("ship_field_agg_two");
+//                for (Terms.Bucket ket : termsTwo.getBuckets()){
+//                    ParsedTopHits topHit = ket.getAggregations().get("ship_field_agg_top1");
+//                    SearchHits searchHit = topHit.getHits();
+//                    SearchHit[] hit = searchHit.getHits();
+//                    for (int i = 0; i < hit.length; i++) {
+//                        if (num>2){
+//                            data.setFluctuateNumber(data.getFluctuateNumber()+1);
+//                            data.setMergeTarget(bucket.getKeyAsString());
+//                            data.setTrackCount(bucket.getDocCount());
+//                            data.setStartTime(query.getStartTime());
+//                            data.setEndTime(query.getEndTime());
+//                            list.add(data);
+//                            num =0;
+//                        }
+//                        if (i != hit.length-1){
+//                            Map<String, Object> map = hit[i].getSourceAsMap();
+//                            Map<String, Object> map2 = hit[i+1].getSourceAsMap();
+//                            Date date = DateUtils.parse(map.get("mergeTime").toString(),"yyyy-MM-dd");
+//                            Date date2 = DateUtils.parse(map2.get("mergeTime").toString(),"yyyy-MM-dd");
+//                            Long interval = date2.getTime()-date.getTime();
+//                            if (interval<6500L){
+//                                num++;
+//                            }
+//                        }
+//                    }
+//                }
+//            }
+//        }
+        try {
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+            String fileName = URLEncoder.encode("虚假推送问题", "UTF-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
+            EasyExcel.write(response.getOutputStream(), FusionData.class).sheet("虚假推送问题")
+                    .doWrite(list);
+        } catch (Exception e) {
+            // 重置response
+            System.out.println("导出虚假推送问题excel失败:{}" + e.getMessage() + e);
+        }
+    }
+
+    @Override
+    public void tianAoLeaveOutExcel(FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        List<LeaveOutData> list = new ArrayList<>();
+        List<LeaceOutDto> dtos = new ArrayList<>();
+        Date startTime = DateUtils.parse(query.getStartTime(),"yyyy-MM-dd");
+        String time = DateUtils.format(startTime,"yyyy-MM-dd");
+        SearchRequest request = new SearchRequest(INDEX_SEAT_TRACK_RADAR+time);
+        // 构建查询条件
+        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+        boolQueryBuilder.filter(QueryBuilders.rangeQuery("receiveTime").gte(query.getStartTime()).lte(query.getEndTime()));
+        searchSourceBuilder.query(boolQueryBuilder);
+//        TermsAggregationBuilder aggBuilder = AggregationBuilders.terms("ship_field_agg")
+//                .field("fusionBatchNum")
+//                .size(query.getPageSize());
+        searchSourceBuilder
+                .trackTotalHits(true)
+//                .aggregation(aggBuilder)
+                .size(query.getPageSize())
+                .sort(SortBuilders.fieldSort("receiveTime").order(SortOrder.ASC))
+                .timeout(TimeValue.timeValueHours(1L))
+                .timeout(TimeValue.timeValueMinutes(30L))
+                .timeout(TimeValue.timeValueSeconds(500L));
+        request.source(searchSourceBuilder);
+        SearchResponse search = client.search(request, COMMON_OPTIONS);
+        SearchHits searchHits = search.getHits();
+        SearchHit[] hits = searchHits.getHits();
+        List<Map<String, Object>> inList = new ArrayList<Map<String, Object>>();
+        List<Map<String, Object>> outList = new ArrayList<Map<String, Object>>();
+        for (SearchHit hit : hits) {
+            Map<String, Object> map = hit.getSourceAsMap();
+            inList.add(map);
         }
+        outList = change(inList, "fusionBatchNum", outList);
+        outList.forEach(map-> {
+                    JSONObject maps = JSONObject.parseObject(JSON.toJSONString(map));
+//            JSONObject maps = new JSONObject();
+//            Iterator it = map.keySet().iterator();
+//            while (it.hasNext()) {
+//                String key = (String) it.next();
+//                maps.put(key, map.get(key));
+//            }
+                    JSONArray jsonArray = JSONArray.parseArray(maps.getString("array"));
+                    if (jsonArray.size() > 0) {
+                        JSONObject job = jsonArray.getJSONObject(0);
+                        LeaceOutDto dto = new LeaceOutDto();
+                        dto.setBatchNumber(job.getString("fusionBatchNum"));
+            dto.setCount((long) jsonArray.size());
+            dtos.add(dto);
+                    }
+                });
+//        Aggregations aggregations = search.getAggregations();
+//        ParsedStringTerms aggregation = aggregations.get("ship_field_agg");
+//        for (Terms.Bucket bucket : aggregation.getBuckets()) {
+//            LeaceOutDto dto = new LeaceOutDto();
+//            dto.setBatchNumber(bucket.getKeyAsString());
+//            dto.setCount(bucket.getDocCount());
+//            dtos.add(dto);
+//        }
+        dtos.forEach(item->{
+            LeaveOutData data = new LeaveOutData();
+            SearchRequest request2 = new SearchRequest(INDEX_SEAT_REALTIMETRAJECTORY_TEST+time);
+            // 构建查询条件
+            BoolQueryBuilder boolQueryBuilder2 = QueryBuilders.boolQuery();
+            SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();
+            boolQueryBuilder2.filter(QueryBuilders.wildcardQuery("trackDeviceNo", "*,"+ item.getBatchNumber() +",*"));
+            boolQueryBuilder2.filter(QueryBuilders.rangeQuery("mergeTime").gte(query.getStartTime()).lte(query.getEndTime()));
+            boolQueryBuilder2.filter(QueryBuilders.termsQuery("mergeType","TA_RADAR"));
+            searchSourceBuilder2.query(boolQueryBuilder2)
+                    .trackTotalHits(true)
+                    .size(query.getPageSize())
+                    .timeout(TimeValue.timeValueHours(1L))
+                    .timeout(TimeValue.timeValueMinutes(30L))
+                    .timeout(TimeValue.timeValueSeconds(500L));
+            request2.source(searchSourceBuilder2);
+            try {
+                SearchResponse search2 = client.search(request2, COMMON_OPTIONS);
+                SearchHits searchHits2 = search2.getHits();
+                Long totalHits = searchHits2.getTotalHits().value;
+                if (totalHits<5) {
+                    SearchHit[] hits2 = searchHits2.getHits();
+                    if (hits2.length > 0) {
+                        Map<String, Object> map = hits2[0].getSourceAsMap();
+                        Map<String, Object> map2 = hits2[hits2.length-1].getSourceAsMap();
+                        data.setMergeTarget(map.get("mergeTarget").toString());
+                        data.setStartTime(map.get("mergeTime").toString());
+                        data.setEndTime(map2.get("mergeTime").toString());
+                        data.setBatchNumber(item.getBatchNumber());
+                        data.setOriginalCount(item.getCount());
+                        data.setTrackCount(totalHits);
+                        list.add(data);
+                    }else {
+                        data.setMergeTarget("未查出匹配融合数据");
+                        data.setStartTime("未查出匹配融合数据");
+                        data.setEndTime("未查出匹配融合数据");
+                        data.setBatchNumber(item.getBatchNumber());
+                        data.setOriginalCount(item.getCount());
+                        data.setTrackCount(totalHits);
+                    }
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        });
         try {
             response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
             response.setCharacterEncoding("utf-8");
-            String fileName = URLEncoder.encode("识别融合数据率波动问题", "UTF-8");
+            String fileName = URLEncoder.encode("天奥轨迹数据遗漏", "UTF-8");
             response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
-            EasyExcel.write(response.getOutputStream(), FusionData.class).sheet("识别融合数据率波动问题")
+            EasyExcel.write(response.getOutputStream(), LeaveOutData.class).sheet("天奥轨迹数据遗漏")
                     .doWrite(list);
         } catch (Exception e) {
             // 重置response
-            log.info("导出excel失败:{}" + e.getMessage() + e);
+            System.out.println("导出天奥轨迹数据遗漏excel失败:{}" + e.getMessage() + e);
+        }
+    }
+
+    @Override
+    public void beiDouLeaveOutExcel(FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        List<LeaveOutData> list = new ArrayList<>();
+        List<LeaceOutDto> dtos = new ArrayList<>();
+        Date startTime = DateUtils.parse(query.getStartTime(),"yyyy-MM-dd");
+        String time = DateUtils.format(startTime,"yyyy-MM-dd");
+        SearchRequest request = new SearchRequest(INDEX_SEAT_TRACK_BEIDOU+time);
+        // 构建查询条件
+        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+        boolQueryBuilder.filter(QueryBuilders.rangeQuery("locationTime").gte(query.getStartTime()).lte(query.getEndTime()));
+        searchSourceBuilder.query(boolQueryBuilder);
+//        TermsAggregationBuilder aggBuilder = AggregationBuilders.terms("ship_field_agg")
+//                .field("fusionBatchNum")
+//                .size(query.getPageSize());
+        searchSourceBuilder
+                .trackTotalHits(true)
+//                .aggregation(aggBuilder)
+                .size(query.getPageSize())
+                .sort(SortBuilders.fieldSort("locationTime").order(SortOrder.ASC))
+                .timeout(TimeValue.timeValueHours(1L))
+                .timeout(TimeValue.timeValueMinutes(30L))
+                .timeout(TimeValue.timeValueSeconds(500L));
+        request.source(searchSourceBuilder);
+        SearchResponse search = client.search(request, COMMON_OPTIONS);
+        SearchHits searchHits = search.getHits();
+        SearchHit[] hits = searchHits.getHits();
+        List<Map<String, Object>> inList = new ArrayList<Map<String, Object>>();
+        List<Map<String, Object>> outList = new ArrayList<Map<String, Object>>();
+        for (SearchHit hit : hits) {
+            Map<String, Object> map = hit.getSourceAsMap();
+            inList.add(map);
+        }
+        outList = change(inList, "devideNo", outList);
+        outList.forEach(map-> {
+            JSONObject maps = JSONObject.parseObject(JSON.toJSONString(map));
+//            JSONObject maps = new JSONObject();
+//            Iterator it = map.keySet().iterator();
+//            while (it.hasNext()) {
+//                String key = (String) it.next();
+//                maps.put(key, map.get(key));
+//            }
+            JSONArray jsonArray = JSONArray.parseArray(maps.getString("array"));
+            if (jsonArray.size() > 0) {
+                JSONObject job = jsonArray.getJSONObject(0);
+                LeaceOutDto dto = new LeaceOutDto();
+                dto.setBatchNumber(job.getString("devideNo"));
+                dto.setCount((long) jsonArray.size());
+                dtos.add(dto);
+            }
+        });
+//        Aggregations aggregations = search.getAggregations();
+//        ParsedStringTerms aggregation = aggregations.get("ship_field_agg");
+//        for (Terms.Bucket bucket : aggregation.getBuckets()) {
+//            LeaceOutDto dto = new LeaceOutDto();
+//            dto.setBatchNumber(bucket.getKeyAsString());
+//            dto.setCount(bucket.getDocCount());
+//            dtos.add(dto);
+//        }
+        dtos.forEach(item->{
+            LeaveOutData data = new LeaveOutData();
+            SearchRequest request2 = new SearchRequest(INDEX_SEAT_REALTIMETRAJECTORY+time);
+            // 构建查询条件
+            BoolQueryBuilder boolQueryBuilder2 = QueryBuilders.boolQuery();
+            SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();
+            boolQueryBuilder2.filter(QueryBuilders.wildcardQuery("trackDeviceNo", "*,"+ item.getBatchNumber() +",*"));
+            boolQueryBuilder2.filter(QueryBuilders.rangeQuery("mergeTime").gte(query.getStartTime()).lte(query.getEndTime()));
+            boolQueryBuilder2.filter(QueryBuilders.termsQuery("mergeType","BEIDOU","AIS_BEIDOU","BEIDOU_RADAR","AIS_BEIDOU_RADAR"));
+            searchSourceBuilder2.query(boolQueryBuilder2)
+                    .trackTotalHits(true)
+                    .size(query.getPageSize())
+                    .timeout(TimeValue.timeValueHours(1L))
+                    .timeout(TimeValue.timeValueMinutes(30L))
+                    .timeout(TimeValue.timeValueSeconds(500L));
+            request2.source(searchSourceBuilder2);
+            try {
+                SearchResponse search2 = client.search(request2, COMMON_OPTIONS);
+                SearchHits searchHits2 = search2.getHits();
+                Long totalHits = searchHits2.getTotalHits().value;
+                if (totalHits<5) {
+                    SearchHit[] hits2 = searchHits2.getHits();
+                    if (hits2.length > 0) {
+                        Map<String, Object> map = hits2[0].getSourceAsMap();
+                        Map<String, Object> map2 = hits2[hits2.length-1].getSourceAsMap();
+                        data.setMergeTarget(map.get("mergeTarget").toString());
+                        data.setStartTime(map.get("mergeTime").toString());
+                        data.setEndTime(map2.get("mergeTime").toString());
+                        data.setBatchNumber(item.getBatchNumber());
+                        data.setOriginalCount(item.getCount());
+                        data.setTrackCount(totalHits);
+                        list.add(data);
+                    }else {
+                        data.setMergeTarget("未查出匹配融合数据");
+                        data.setStartTime("未查出匹配融合数据");
+                        data.setEndTime("未查出匹配融合数据");
+                        data.setBatchNumber(item.getBatchNumber());
+                        data.setOriginalCount(item.getCount());
+                        data.setTrackCount(totalHits);
+                    }
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        });
+        try {
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+            String fileName = URLEncoder.encode("北斗轨迹数据遗漏", "UTF-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
+            EasyExcel.write(response.getOutputStream(), LeaveOutData.class).sheet("北斗轨迹数据遗漏")
+                    .doWrite(list);
+        } catch (Exception e) {
+            // 重置response
+            System.out.println("导出北斗轨迹数据遗漏excel失败:{}" + e.getMessage() + e);
+        }
+    }
+
+    @Override
+    public void hlxyjrhLeaveOutExcel(FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        List<LeaveOutData> list = new ArrayList<>();
+        List<LeaceOutDto> dtos = new ArrayList<>();
+        Date startTime = DateUtils.parse(query.getStartTime(),"yyyy-MM-dd");
+        String time = DateUtils.format(startTime,"yyyy-MM-dd");
+        SearchRequest request = new SearchRequest(INDEX_SEAT_HLX_FUSION_SHIP+time);
+        // 构建查询条件
+        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+        boolQueryBuilder.filter(QueryBuilders.rangeQuery("time").gte(query.getStartTime()).lte(query.getEndTime()));
+        searchSourceBuilder.query(boolQueryBuilder);
+//        TermsAggregationBuilder aggBuilder = AggregationBuilders.terms("ship_field_agg")
+//                .field("fusionBatchNum")
+//                .size(query.getPageSize());
+        searchSourceBuilder
+                .trackTotalHits(true)
+//                .aggregation(aggBuilder)
+                .size(query.getPageSize())
+                .sort(SortBuilders.fieldSort("time").order(SortOrder.ASC))
+                .timeout(TimeValue.timeValueHours(1L))
+                .timeout(TimeValue.timeValueMinutes(30L))
+                .timeout(TimeValue.timeValueSeconds(500L));
+        request.source(searchSourceBuilder);
+        SearchResponse search = client.search(request, COMMON_OPTIONS);
+        SearchHits searchHits = search.getHits();
+        SearchHit[] hits = searchHits.getHits();
+        List<Map<String, Object>> inList = new ArrayList<Map<String, Object>>();
+        List<Map<String, Object>> outList = new ArrayList<Map<String, Object>>();
+        for (SearchHit hit : hits) {
+            Map<String, Object> map = hit.getSourceAsMap();
+            inList.add(map);
+        }
+        outList = change(inList, "targetID", outList);
+        outList.forEach(map-> {
+            JSONObject maps = JSONObject.parseObject(JSON.toJSONString(map));
+//            JSONObject maps = new JSONObject();
+//            Iterator it = map.keySet().iterator();
+//            while (it.hasNext()) {
+//                String key = (String) it.next();
+//                maps.put(key, map.get(key));
+//            }
+            JSONArray jsonArray = JSONArray.parseArray(maps.getString("array"));
+            if (jsonArray.size() > 0) {
+                JSONObject job = jsonArray.getJSONObject(0);
+                LeaceOutDto dto = new LeaceOutDto();
+                dto.setBatchNumber(job.getString("targetID"));
+                dto.setCount((long) jsonArray.size());
+                dtos.add(dto);
+            }
+        });
+//        Aggregations aggregations = search.getAggregations();
+//        ParsedStringTerms aggregation = aggregations.get("ship_field_agg");
+//        for (Terms.Bucket bucket : aggregation.getBuckets()) {
+//            LeaceOutDto dto = new LeaceOutDto();
+//            dto.setBatchNumber(bucket.getKeyAsString());
+//            dto.setCount(bucket.getDocCount());
+//            dtos.add(dto);
+//        }
+        dtos.forEach(item->{
+            LeaveOutData data = new LeaveOutData();
+            SearchRequest request2 = new SearchRequest(INDEX_SEAT_REALTIMETRAJECTORY_TEST+time);
+            // 构建查询条件
+            BoolQueryBuilder boolQueryBuilder2 = QueryBuilders.boolQuery();
+            SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();
+            boolQueryBuilder2.filter(QueryBuilders.wildcardQuery("trackDeviceNo", "*,"+ item.getBatchNumber() +",*"));
+            boolQueryBuilder2.filter(QueryBuilders.rangeQuery("mergeTime").gte(query.getStartTime()).lte(query.getEndTime()));
+            boolQueryBuilder2.filter(QueryBuilders.termsQuery("mergeType","HLX_AIS_RADAR","HLX_AIS","HLX_RADAR","HLX_ZYD_RADAR"));
+            searchSourceBuilder2.query(boolQueryBuilder2)
+                    .trackTotalHits(true)
+                    .size(query.getPageSize())
+                    .timeout(TimeValue.timeValueHours(1L))
+                    .timeout(TimeValue.timeValueMinutes(30L))
+                    .timeout(TimeValue.timeValueSeconds(500L));
+            request2.source(searchSourceBuilder2);
+            try {
+                SearchResponse search2 = client.search(request2, COMMON_OPTIONS);
+                SearchHits searchHits2 = search2.getHits();
+                Long totalHits = searchHits2.getTotalHits().value;
+                if (totalHits<5) {
+                    SearchHit[] hits2 = searchHits2.getHits();
+                    if (hits2.length > 0) {
+                        Map<String, Object> map = hits2[0].getSourceAsMap();
+                        Map<String, Object> map2 = hits2[hits2.length-1].getSourceAsMap();
+                        data.setMergeTarget(map.get("mergeTarget").toString());
+                        data.setStartTime(map.get("mergeTime").toString());
+                        data.setEndTime(map2.get("mergeTime").toString());
+                        data.setBatchNumber(item.getBatchNumber());
+                        data.setOriginalCount(item.getCount());
+                        data.setTrackCount(totalHits);
+                        list.add(data);
+                    }else {
+                        data.setMergeTarget("未查出匹配融合数据");
+                        data.setStartTime("未查出匹配融合数据");
+                        data.setEndTime("未查出匹配融合数据");
+                        data.setBatchNumber(item.getBatchNumber());
+                        data.setOriginalCount(item.getCount());
+                        data.setTrackCount(totalHits);
+                    }
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        });
+        try {
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+            String fileName = URLEncoder.encode("海兰信1级融合轨迹数据遗漏", "UTF-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
+            EasyExcel.write(response.getOutputStream(), LeaveOutData.class).sheet("海兰信1级融合轨迹数据遗漏")
+                    .doWrite(list);
+        } catch (Exception e) {
+            // 重置response
+            System.out.println("导出海兰信1级融合轨迹数据遗漏excel失败:{}" + e.getMessage() + e);
+        }
+    }
+
+    @Override
+    public void tianaoStaticOrDynamicLeaveOutExcel(FusionQuery query, HttpServletResponse response) throws IOException, ParseException {
+        List<StaticOrDynamicData> list = new ArrayList<>();
+        List<LeaceOutDto> dtos = new ArrayList<>();
+        Date startTime = DateUtils.parse(query.getStartTime(),"yyyy-MM-dd");
+        String time = DateUtils.format(startTime,"yyyy-MM-dd");
+        SearchRequest request = new SearchRequest(INDEX_SEAT_TRACK_RADAR+time);
+        // 构建查询条件
+        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
+        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
+        boolQueryBuilder.filter(QueryBuilders.rangeQuery("receiveTime").gte(query.getStartTime()).lte(query.getEndTime()));
+        boolQueryBuilder.mustNot(QueryBuilders.termQuery("targetProper","0"));
+        searchSourceBuilder.query(boolQueryBuilder);
+//        TermsAggregationBuilder aggBuilder = AggregationBuilders.terms("ship_field_agg")
+//                .field("fusionBatchNum")
+//                .size(query.getPageSize());
+        searchSourceBuilder
+                .trackTotalHits(true)
+//                .aggregation(aggBuilder)
+                .size(query.getPageSize())
+                .timeout(TimeValue.timeValueHours(1L))
+                .timeout(TimeValue.timeValueMinutes(30L))
+                .timeout(TimeValue.timeValueSeconds(500L));
+        request.source(searchSourceBuilder);
+        SearchResponse search = client.search(request, COMMON_OPTIONS);
+        SearchHits searchHits = search.getHits();
+        SearchHit[] hits = searchHits.getHits();
+        List<Map<String, Object>> inList = new ArrayList<Map<String, Object>>();
+        List<Map<String, Object>> outList = new ArrayList<Map<String, Object>>();
+        for (SearchHit hit : hits) {
+            Map<String, Object> map = hit.getSourceAsMap();
+            inList.add(map);
+        }
+        outList = change(inList, "fusionBatchNum", outList);
+        outList.forEach(map-> {
+            JSONObject maps = JSONObject.parseObject(JSON.toJSONString(map));
+//            JSONObject maps = new JSONObject();
+//            Iterator it = map.keySet().iterator();
+//            while (it.hasNext()) {
+//                String key = (String) it.next();
+//                maps.put(key, map.get(key));
+//            }
+            JSONArray jsonArray = JSONArray.parseArray(maps.getString("array"));
+            if (jsonArray.size() > 0) {
+                JSONObject job = jsonArray.getJSONObject(0);
+                LeaceOutDto dto = new LeaceOutDto();
+                dto.setBatchNumber(job.getString("fusionBatchNum"));
+                dto.setCount((long) jsonArray.size());
+                dtos.add(dto);
+            }
+        });
+        dtos.forEach(item->{
+            StaticOrDynamicData data = new StaticOrDynamicData();
+            SearchRequest request2 = new SearchRequest(INDEX_SEAT_REALTIMETRAJECTORY_TEST+time);
+            // 构建查询条件
+            BoolQueryBuilder boolQueryBuilder2 = QueryBuilders.boolQuery();
+            SearchSourceBuilder searchSourceBuilder2 = new SearchSourceBuilder();
+            boolQueryBuilder2.filter(QueryBuilders.wildcardQuery("trackDeviceNo", "*,"+ item.getBatchNumber() +",*"));
+            boolQueryBuilder2.filter(QueryBuilders.termQuery("targetType","0"));
+            boolQueryBuilder2.filter(QueryBuilders.rangeQuery("mergeTime").gte(query.getStartTime()).lte(query.getEndTime()));
+            boolQueryBuilder2.filter(QueryBuilders.termsQuery("mergeType","RADAR","AIS_RADAR","BEIDOU_RADAR","AIS_BEIDOU_RADAR"));
+            searchSourceBuilder2.query(boolQueryBuilder2)
+                    .trackTotalHits(true)
+                    .size(query.getPageSize())
+                    .timeout(TimeValue.timeValueHours(1L))
+                    .timeout(TimeValue.timeValueMinutes(30L))
+                    .timeout(TimeValue.timeValueSeconds(500L));
+            request2.source(searchSourceBuilder2);
+            try {
+                SearchResponse search2 = client.search(request2, COMMON_OPTIONS);
+                SearchHits searchHits2 = search2.getHits();
+                SearchHit[] hits2 = searchHits2.getHits();
+                if (hits2.length > 0) {
+                    JSONObject sourceItem = JSONObject.parseObject(hits2[0].getSourceAsString());
+                    data.setMergeTarget(sourceItem.getString("mergeTarget"));
+                    data.setBatchNumber(item.getBatchNumber());
+                    list.add(data);
+                }else {
+                    data.setMergeTarget("未查出匹配融合数据");
+                    data.setBatchNumber(item.getBatchNumber());
+                    list.add(data);
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        });
+        try {
+            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+            response.setCharacterEncoding("utf-8");
+            String fileName = URLEncoder.encode("天奥静态数据与动态轨迹融合", "UTF-8");
+            response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");
+            EasyExcel.write(response.getOutputStream(), StaticOrDynamicData.class).sheet("天奥静态数据与动态轨迹融合")
+                    .doWrite(list);
+        } catch (Exception e) {
+            // 重置response
+            System.out.println("导出天奥静态数据与动态轨迹融合excel失败:{}" + e.getMessage() + e);
+        }
+    }
+
+    /**
+     * 按照List<Map<String,Object>>里面map的某个value重新封装成多个不同的list, 原始数据类型List<Map<String,Object>>, 转换后数据类型Map<String,List<Map<String,Object>>>
+     * @param inList
+     * @param oneMapKey
+     * @param outList
+     * @return
+     */
+    private static List<Map<String, Object>> change(List<Map<String, Object>> inList, String oneMapKey,
+                                                    List<Map<String, Object>> outList) {
+        // 1.将某个key的值存在set中
+        Set<Object> setTmp = new HashSet<Object>();
+        for (Map<String, Object> tmp : inList) {
+            setTmp.add(tmp.get(oneMapKey));
+        }
+        // 2.遍历set
+        Iterator<Object> it = setTmp.iterator();
+        while (it.hasNext()) {
+            String oneMapValueStr = "";
+            String oneSetTmpStr = (String) it.next();
+            Map<String, Object> oneSetTmpMap = new HashMap<String, Object>();
+            List<Map<String, Object>> oneSetTmpList = new ArrayList<Map<String, Object>>();
+
+            for (Map<String, Object> tmp : inList) {
+                oneMapValueStr = (String) tmp.get(oneMapKey);
+                if (oneSetTmpStr.equals(oneMapValueStr)) {
+                    oneSetTmpMap.put("text", oneSetTmpStr);
+                    oneSetTmpList.add(tmp);
+                }
+            }
+            oneSetTmpMap.put("array", oneSetTmpList);
+            outList.add(oneSetTmpMap);
+        }
+        return outList;
+    }
+
+
+    public Long dateUtils(Long oneTime,Long twoTime){
+        if (oneTime>twoTime){
+            return oneTime-twoTime;
+        }else {
+            return twoTime-oneTime;
         }
     }
-}
+}

+ 8 - 8
fusion-analysis/src/main/resources/application.yml

@@ -3,12 +3,12 @@ server:
 
 spring:
   application.name: fusion-analysis
-  profiles.active: prod
+#  profiles.active: prod
 
-#taiji:
-#  elasticsearch.rest:
-#    uris: 120.25.233.10:9200
-#    username: elastic       #如果你设置了基于x-pack的验证就要填写账号和密码
-#    password: root@2022!       #没有则不用配置
-#    connection-timeout: 100 #连接超时
-#    max-connection: 100  #最大连接数
+taiji:
+  elasticsearch.rest:
+    uris: 120.25.233.10:9200
+    username: elastic       #如果你设置了基于x-pack的验证就要填写账号和密码
+    password: root@2022!       #没有则不用配置
+    connection-timeout: 100 #连接超时
+    max-connection: 100  #最大连接数